tag:blogger.com,1999:blog-48364972345808157032023-06-15T14:30:56.150+05:30It's all abt TamilTamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.comBlogger37125tag:blogger.com,1999:blog-4836497234580815703.post-82671927474672240322019-02-06T21:36:00.000+05:302019-11-30T01:01:21.906+05:30Career Means Commitment <div style="font-size:14px;color:#383838 ">It has been a while since I last wrote. Wished to revisit with an introspective post. Having traveled close to 8 years along, Media.net stands only second to my Matriculation Board in years of association with an institution. Starting a freshman out of graduation, I now stand as a Lead helping my peers shape a career for themselves. As a part of the parcel, peers resigning from their positions stating reasons varied between studies and other exciting opportunities in hand had to happen once in a while. From my 8 Years, having experienced a mix, I would be seen discussing from one end of the table with hopes to bring clarity in minds of peers over the other end, before they will call it curtains officially. Not so golden, still writing the discussion down might help a few I felt. These might be very specific to my organization or even team, still, recommend reading once.<br />
<br />
<h3>Rule of Expectation:</h3><ul><li><b>Criteria to MEET EXPECTATION </b><br />
<ol><li>Deliver Consistently and Reliably (primary reason we are hired for)</li>
</ol></li>
<li><b>Criteria to EXCEED EXPECTATION</b><br />
<ol><li>Understand WHY have you been asked to deliver something</li>
<li>Connect with the product</li>
<li>Invest Time & Create opportunities</li>
<li>Deliver them</li>
<li>Don’t complain, improve instead</li>
<li>Contribute to the good of fellow developers (team members)</li>
</ol></ul>At the end of every cycle evaluate yourself on the category you fall. If you MEET then you deserve a Standard appreciation. If you EXCEED then you deserve a Positive Deviation from Standard. Understand the evaluation. Question if there is a disagreement. They help you grow. As well accept, that magnitude of appreciation can’t be same every time. But cumulatively you’ll be happy if you can EXCEED every time and stay longer. <center><blockquote style="font-size:40px">“Career is at least 20 Years Long. Don’t be Myopic”</blockquote></center><h3>Rule of Patience & Growth:</h3><p>By nature, everything takes time to grow. Given we keep the seeds nourished consistently and wait with patience. Stages of growth according to me</p><ul><li>Year ONE - Become proficient within your Boundary and Deliver</li>
<li>Year TWO - Create opportunities within Boundary</li>
<li>Year THREE - Experience Mentorship</li>
<li>Year FOUR - Excel Art of Delivering through a Team & Break the Boundary</li>
<li>Year FIVE - Let your Team Create opportunities</li>
</ul><p>That I call is a <b>foundation</b>. And it takes its own time. But once it is laid, you lead. If you lose your patience and focus anywhere in this process, be ready to restart.</p><h3>Rule of Trust:</h3><p>No organization can run on experiment mode every day. Every project will naturally follow phases of development. After a few initial phases, there will come a phase when there will be close to nil experiments. But that doesn’t mean there won’t be opportunities anymore. Have patience but be hungry. Trust leadership. Everything around us happens for a reason from where you sit till what you deliver and where you stand now in your career path. Trust leadership.</p><h3>Rule of Switching:</h3><p>Switch Career, not Yet Another Job (If you don’t hate current one to the core or it is at risk)</p><ul><li>Studies</li>
<li>Building your own Idea or Co-Founding</li>
<li>Change of Field (Outside of Development or your area of work)</li>
<li>Whole new level of responsibility</li>
</ul><p>Why NO to Switch to yet another Job?</p><ul><li>You destroy the foundation you laid</li>
<li>You destroy the reputation you earned</li>
<li>You might lose peace of your mind</li>
<li>You are likely to switch again</li>
</ul><center><blockquote style="font-size:30px">“Experience is measured in Years, Career rather by growth”</blockquote></center><h3>Rule of Silence:</h3><p>Never be vocal about appreciations, evaluations or switching with peers. That’s underestimating yourself. If you think you are denied what you deserved, talk to people who can change it.</p><h3>Rule of Communication:</h3><p>Always communicate to right contact before coming to conclusions. There might be a solution or a reason with them.</p><h3>Rule of Acceptance:</h3><p>Feedback is a very important process of career development. Ready to accept feedbacks that are given to improve you. They don’t blame or judge you, instead of wishing you to enhance and grow. If only way to skip suggestive feedback is switching, then there won’t be a career. But if ears are kept open for honest feedbacks your growth will be inevitable.</p><h3>Rule of Ageing:</h3><p>When you grow older in a place, you are likely to get laid back and pushed towards a comfort zone. Never Settle. Stay Hungry.</p><center><blockquote style="font-size:30px">“When you die, you must die as a hero”</blockquote></center><b>Some Careers to Look out for</b> <ul><li><a href="https://en.wikipedia.org/wiki/Sundar_Pichai">Sundar Pichai</a></li>
<li><a href="https://www.computerworlduk.com/it-leadership/who-is-thomas-kurian-new-google-cloud-ceo-3687161/">Thomas Kurian</a></li>
<li><a href="https://en.wikipedia.org/wiki/Satya_Nadella">Satya Nadella</a></li>
</ul>
And many more @our own workplaces. They all stay not because they couldn’t switch, instead, they understand what makes a career. <blockquote style="font-size:25px; text-align: justify">Even an organization whose mission is what your passion is can only give you a Job. Making it a career is left to you. Hence never switch a Job for Job. Instead Choose Careers Wisely.</blockquote></div>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-47939203242260240152014-10-08T16:10:00.000+05:302014-10-08T16:14:11.809+05:30Selenium Webdriver in Nodejs + JavascriptPhewww getting back to blog after almost an year.<br />
So, am back to discuss an interesting node module selenium-webdriver [Ref: <a href="https://code.google.com/p/selenium/wiki/WebDriverJs">Project Doc</a> and <a href="https://www.npmjs.org/package/selenium-webdriver">npm registry</a>]<br />
Am assuming the reader has prior knowledge on what <a href="http://nodejs.org">nodejs</a>, <a href="http://npmjs.org">npm and node modules</a> are. And a little bit of selenium fun ;)<br />
What is selenium?<br />
As <a href="http://en.wikipedia.org/wiki/Selenium_(software)">wiki</a> says, Selenium is a portable software testing framework for web applications.<br />
It is a prominently used tool for browser automation. For further details checkout <a href="http://www.seleniumhq.org/">SeleniumHQ</a>.<br />
<br />
What are we doing here?<br />
Basically Selenium provides bindings in many languages like java, python, php and now even nodejs. <br />
Here am planning to run through few code samples of using selenium webdriver in nodejs.<br />
<br />
<b>Where to start?</b><br />
<pre class="brush:plain">im@mylaptop$ npm install --save selenium-webdriver
</pre><br />
<b>A Simple Webdriver Example</b><br />
<pre class="brush:javascript">// Import Selenium Dependency
var Webdriver = require('selenium-webdriver');
// Few Settings
var PAGE_LOAD_TIMEOUT_MS = 10000;
var SCRIPT_LOAD_TIMEOUT_MS = 1000;
var WINDOW_WIDTH_PX = 1024;
var WINDOW_HEIGHT_PX = 768;
// Initialize a webdriver with desired capabilites
var driver = new Webdriver.Builder().withCapabilities(Webdriver.Capabilities.firefox()).build();
// Manage timeouts of the webdriver instance
driver.manage().timeouts().pageLoadTimeout(PAGE_LOAD_TIMEOUT_MS);
driver.manage().timeouts().setScriptTimeout(SCRIPT_LOAD_TIMEOUT_MS);
// Manage window settings of the webdriver instance
driver.manage().window().setSize(WINDOW_WIDTH_PX, WINDOW_HEIGHT_PX);
// Request to render google.com
driver.get("http://google.com").then(function () {
// On Success get the title of the rendered page
driver.getTitle().then(function (title) {
// On Success log it out
console.log(title);
});
});
</pre><br />
<i>// Initialize a webdriver with desired capabilites</i><br />
<b>What are the default capabilities?</b><br />
Checkout <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/capabilities.js#68">capabilities.js</a><br />
It includes<br />
1. BROWSER_NAME<br />
2. SUPPORTS_JAVASCRIPT<br />
3. SUPPORTS_CSS_SELECTORS<br />
4. TAKES_SCREENSHOT<br />
<br />
<pre class="brush:javascript">Webdriver.Capabilities.firefox()
</pre>Creates a new capabilities object by overriding the default BROWSER_NAME from <i>'browserName' to 'firefox'</i>.<br />
<br />
<b>So, What are all other browser options?</b><br />
Checkout <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/capabilities.js#32"> Browsers Section </a><br />
<br />
<b>Do all the browsers work by default?</b><br />
Not really. To initialize a webdriver, we need to make sure that executable of desired browser is present in the system <b>PATH</b>.<br />
For Ex: To use firefox, the following should be checked. If this fails, then appropriate binaries should be installed.<br />
<br />
<pre class="brush:plain">iam@mylaptop$ which firefox
/usr/bin/firefox
</pre><br />
Apart from this, few browsers use separate driver executables to abstract the communication via webdriver to actual browser. For Ex: Chrome needs <a href="http://chromedriver.storage.googleapis.com/index.html">chromedriver</a>. Download and make sure it is available in the system <b>PATH</b>.<br />
<i>Internally chromedriver expects google-chrome to be available in the system <b>PATH</b>.</i><br />
<br />
What if I wish to start chrome or firefox from webdriver with specific options?<br />
<pre class="brush:javascript">var driver = new Webdriver.Builder().withCapabilities(Webdriver.Capabilities.firefox()).setFirefoxOptions({
firefox_profile: "Name"
}).build();
</pre><br />
<b>How do I manage exceptions while loading [like pageload timesout]?</b><br />
Selenium webdriver is full of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promises</a>. Almost every interaction with the webdriver [irrespective of whether it is sync or async] returns a promise.<br />
As we can see in our code,<br />
<pre class="brush:javascript">driver.get("http://google.com").then(function success() {
console.log('Successful');
i++;
}, function error(err) {
console.log(err);
}).thenCatch(function (e) {
console.log("Any exceptions in success or err callbacks gets thrown here", e);
// You need to decide the resolution value here
}).thenFinally(function () {
console.log("We can tear down stuffs here");
// You need to decide the resolution value here. If nothing specified undefined will be returned.
});
</pre><br />
<b>How do I handle actions that are dependent on some conditions [like may be after some ajax calls you need click some button]?</b><br />
We can ask driver to wait <a href="http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#implicit-waits">implicitly</a> on a timeout basis or <a href="http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp#explicit-waits">explicitly</a> on a condition basis.<br />
<pre class="brush:javascript">driver.sleep(MY_SLEEPTIMER_MS).then(function () {
console.log("I'll do my action");
});
driver.wait(function () {
if (document.readyState === "complete") {
return true;
}
}, TIMEOUT_TO_WAIT).then(function () {
console.log("I'll do my action here");
}, function () {
console.log("Either the condn satisfied or the TIMEOUT_TO_WAIT happened; luck is yours");
});
</pre><br />
<b>How do I access dom?</b><br />
It is pretty simple as we do in javascript.<br />
<pre class="brush:javascript">driver.findElement(Webdriver.By.name('test')).then(function (element) {
element.click();
});
// Other options
// Webdriver.By.tagName
// Webdriver.By.id
// Webdriver.By.css [all valid css selectors works]
// Webdriver.By.xpath
// Many more..
</pre>Check out full list <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/locators.js#212">here</a><br />
You can use <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#864">findElements</a> to get a list of matched elements.<br />
<br />
<b>Can we do it on multiple attributes?</b><br />
Yep we could do that too.<br />
<pre class="brush:javascript">var webElement = driver.findElement({
css: '#myselector',
tagName: 'div'
});
// We can even detect elements within scope of another element
var img = webElement.findElement(Webdriver.By.tagName("img"));
</pre>The result of the findElement Query is chainable [it is of type <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#2063">WebElementPromise</a>].<br />
<pre class="brush:javascript">function getInputElement(driver) {
return driver.findElement(Webdriver.By.css("input[type='search']")).then(null, function () {
return driver.findElement(Webdriver.By.css("input[id*='search']"));
}).then(null, function () {
return driver.findElement(Webdriver.By.css("input[name*='search']"));
});
}
// Fill input with value ABC
getInputElement(driver).then(function (element) {
element.sendKeys("ABC");
});
</pre><br />
<b>Will we be able to execute a custom script of mine in the page's context?</b><br />
Yes, Absolutely<br />
<pre class="brush:javascript">var myscript = "return document.title";
driver.executeScript(myScript).then(function (value) {
console.log("document title is ", value);
});
</pre>Check <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js#534">executeAsyncScript<a> as well. It might interest you.<br />
<br />
<b>What else can we do?</b><br />
<a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/webdriver.js">webdriver.js</a> is the best documented code I have seen so far. <br />
It explains all the webdriver apis to dot. Check it out.<br />
<br />
<u>Points to remember:</u><br />
1. Although driver.get returns promise, it is a completely synchronous task and it blocks the nodejs single thread. Beware of this :)<br />
2. You need chromedriver to use Chrome as your Client Browser.<br />
3. findElement returns a chainable promise cum webElement.<br />
4. We can send non printable keys as well using sendKeys. Check <a href="https://code.google.com/p/selenium/source/browse/javascript/webdriver/key.js#25">list</a> of keys supported.<br />
5. Actions like submit and click will make the driver wait, when they result in redirection but actions like Webdriver.key.ENTER or RETURN won't.<br />
6. Last but not the least <a href="https://code.google.com/p/selenium/source/browse/#git%2Fjavascript%2Fwebdriver">these</a> are the core webdriver files<br />
7. You can use <a href="https://code.google.com/p/selenium/wiki/WebDriverJs#Using_the_Stand-alone_Selenium_Server">selenium standalone server</a> to communicate to a remote webdriver too.<br />
7. Do checkout <a href="http://webdriver.io">webdriver.io</a>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-42377079062417300982013-12-27T20:30:00.000+05:302013-12-30T11:30:10.051+05:30The Year 2K13 Was....<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
</div>
As we are at the verge of year 2K13, I asked a question to my inner self<br />
<b>How did it go?</b><br />
From there on my mind started recalling events, that went past me in the journey. <br />
The journey that made me an year older with handful of new experiences.<br />
2K13 in my calendar is going to be one of the most unfogettable year in both the ways [Happiness & its counterpart].<br />
<b>January:</b><br />
All the waves into both work and life because of relocation from mumbai to bangalore [Oct 2012] were slowly settling down.<br />
Had Durga to fill the void left in my work as a companion. Someone to discuss and share. And forgot to say, now we are a team ;)<br />
Realized that I got promoted from Web Dev to R&D Engg.<br />
Gave good support to my Super DAD who was taking care of our dream home which was under construction.<br />
<i>Bottom Line: Realized that there is a lot more to do than work in life and Patience rewards</i><br />
<br />
<b>February:</b><br />
Feb 22 - One of the important events in our family till then, was planned. Our House warming ceremony. My Dad's moment of pride.<br />
Over all the odds, function ended with a note of happiness and pride. Had all my teachers who are the reason for who am now, friends and lots of relatives come home.<br />
Gifted my father for the first time on his birthday after I started my earning. A nice TITAN wrist watch [Getting Goose Bumps even now].<br />
First birthday of two of my nephews in the same month.<br />
Hemanth Sagar Shifted to Bangalore from Mumbai. And now we are 3 heads up.<br />
<i>Bottom Line: Remembering people who had an impact in your growth in life is a respect you give back to them.</i><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-x-9TSBo-hao/Ur2LztdsvtI/AAAAAAAAC0g/z3NTEMRxY4A/s1600/invite.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://2.bp.blogspot.com/-x-9TSBo-hao/Ur2LztdsvtI/AAAAAAAAC0g/z3NTEMRxY4A/s320/invite.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Housewarming Invite</td></tr>
</tbody></table>
<br />
<b>March:</b><br />
Joined Music and Metals [Body Fitness Center] on March 12th. <br />
Can't even say how much value it does add to me now. Never ever thought this could be such a good thing happening to me back then.<br />
Although I Initially joined to reimburse Health and Fitness component at office, Now I swear I stopped reimbursing them.<br />
All credits to Jibin [Trainer & Best Pal] who changed the meaning of workouts to fun and brought people together as a family.<br />
<i>Bottom Line: Passion drives people [Dedicated to Jibin]</i><br />
<br />
<b>April:</b><br />
April 26th - Marked 3rd anniversary and another year awaiting.<br />
Home Construction was well in progress and heated up to reach the end.<br />
And one of my roommates Deepan Chakravarthy got engaged. Best Surprising moment of the year ;)<br />
<i>Bottom Line: There is always a hidden random surprise awaits us [Dedicated to Deepan :D]</i><br />
<br />
<b>May:</b><br />
Practised for my first 10K marathon with my companion Durga. Would wish to revisit <a href="http://itsallabtamil.blogspot.in/2013/05/tcsw10k-run-for-AIFO.html">this post</a>.<br />
Thanks to Dr. Manimozhi & AIFO for giving us such an awesome opportunity.<br />
May 19th - Finished the marathon in 1 Hr and 2 min.<br />
May 20th - My first intern Apurv joined the team.<br />
May 22nd - My sister, classmate and bestest friend Yogi's engagement.<br />
May 22nd - Deepan's marriage.<br />
May 25th - Completed Year 2 @Media.net<br />
Visited Chennai to attend the marriage. Met my partner [Chandru] after almost 3 months.<br />
It was a really nice re-union with Nizha, Kanmani [My Sister] and Chandru at Buhari.<br />
Kushagra Shifted to Bangalore from Mumbai. And we are 4 heads up.<br />
Volunteered LokSatta Party on the election day in Bangalore with Vignesh.<br />
<i>Bottom Line: Determination defines you and what you can.</i><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/--vaq0JAqyP4/UZnz02IYvbI/AAAAAAAABW8/Z-P8YLX5DMw/s1600/965004_4594398378739_1272556509_o.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://4.bp.blogspot.com/--vaq0JAqyP4/UZnz02IYvbI/AAAAAAAABW8/Z-P8YLX5DMw/s320/965004_4594398378739_1272556509_o.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Team AIFO and M&M after marathon</td></tr>
</tbody></table>
<br />
<b>June:</b><br />
June 9th - Participated in Corporate relay 5K * 4 with Kushagra, Hemanth, Durga and our manager cum partner Chandru<br />
It was good going with Apurv on his internship and as well at my work.<br />
June 12-13 - Yogi's Marriage at Coimbatore. Couldn't even believe that a kutti friend [small] of mine was getting married. Ufffff.. 23 Yrs Gone..<br />
Had a really nice long chat with Elempirai [Another School Friend of mine] on our way back to home. Almost we shared everything.<br />
<i>Bottom Line: Learning never stops</i><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-prn2/977959_4948605484036_1625160631_o.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="180" src="https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-prn2/977959_4948605484036_1625160631_o.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">After Corporate Relay</td></tr>
</tbody></table>
<br />
<b>July:</b><br />
Visited my beloved partner's home town for the first time in 5 yrs [Sankaran Kovil]. One very memorable trip.<br />
Bike ride to coutrallam in continuously drizzling weather and Fun in the falls was the best out of all.<br />
More than everything else, we celebrated my partner's birthday at his hometown [Fullfilled his childhood dream of cutting cake at his home :P]<br />
Helped my partner to meet his fiancee for the first time [with Venky and Ramesh].<br />
2 days of complete enjoyment made it for the whole month.<br />
<i>Bottom Line: Making your close ones happy is one of the richest feeling :)</i><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://scontent-b.xx.fbcdn.net/hphotos-prn1/q71/s720x720/1016707_10151571737168983_972914307_n.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="240" src="https://scontent-b.xx.fbcdn.net/hphotos-prn1/q71/s720x720/1016707_10151571737168983_972914307_n.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Coutrallam</td></tr>
</tbody></table>
<br />
<b>August:</b><br />
August 10th - First away trip at Music and Metals team to Chunchi Falls & Mekadatu. So, much fun it was. Took my partner with me. Made him visit Bangalore from Chennai.<br />
Visited home town for a 4 days long weekend. Spent some good time off from home with my family.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-ash4/965790_10151831253975903_100263899_o.jpghttps://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-ash4/965790_10151831253975903_100263899_o.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="240" src="https://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-ash4/965790_10151831253975903_100263899_o.jpghttps://fbcdn-sphotos-h-a.akamaihd.net/hphotos-ak-ash4/965790_10151831253975903_100263899_o.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Falls in the back drop</td></tr>
</tbody></table>
<br />
<b>September:</b><br />
September 9th - We entered our dream home. It was complete by then. All credits to my Dad. Almost 2yrs of his life was spent on it.<br />
September 17th - Completed one year in bangalore :)<br />
September 29th - After a complete year being in bangalore finally I met my closest buddy Selva only for the Second time :o <br />
We watched a movie [Onaiyum Aatukutiyum] and did swimming at BAC<br />
<i>Bottom Line: True friends don't complaint. Coz they know you :D [Dedicated to Selva]</i><br />
<br />
<b>October:</b><br />
Two mentees Vedant and Vivek joined hands with us in Bangalore for media.net.<br />
We rocked the Directi Annual Bash :)<br />
Got Promoted as Senior R&D Engg. Promotion Number 2 in 2 yrs :) Awesome place to work with. Recognition of good work at its best.<br />
<i>Bottom Line: Keep focused and Keep moving. There is lot more heights to reach :)</i><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://fbcdn-sphotos-a-a.akamaihd.net/hphotos-ak-ash3/1385251_509846115777550_46254750_n.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="212" src="https://fbcdn-sphotos-a-a.akamaihd.net/hphotos-ak-ash3/1385251_509846115777550_46254750_n.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Directi Annual Party</td></tr>
</tbody></table>
<br />
<b>November:</b><br />
Nov 2nd - Diwali Diwali Diwali... First Diwali at our new home :) <br />
Yogi visited our home with her hubby for the first time after marriage.<br />
Nov 15th - My Cousin Sister gave birth to Shruthika :) Happy Moment.<br />
My first dream come true. My Bike. I said MY BIKE. Got my Yamaha FZS delivered just a day before my birthday :)<br />
Nov 17th - One of the best birthday celebration till date. 12 o'clock cake cut on road with Jibin Akash and Balaji. Long drive. And meeting with special friends ;)<br />
<i>Bottom Line: Full filling your own dreams adds more meaning to your life :)</i><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-bDRJxSoI-3c/Ur2OPA9m_eI/AAAAAAAAC0s/o-NxWk-jKQg/s1600/IMG_20131115_174055.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://1.bp.blogspot.com/-bDRJxSoI-3c/Ur2OPA9m_eI/AAAAAAAAC0s/o-NxWk-jKQg/s320/IMG_20131115_174055.jpg" width="240" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">MY BIKE</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://fbcdn-sphotos-b-a.akamaihd.net/hphotos-ak-prn1/560121_10152066986530903_47469758_n.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="240" src="https://fbcdn-sphotos-b-a.akamaihd.net/hphotos-ak-prn1/560121_10152066986530903_47469758_n.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My B'day Celeb at M&M</td></tr>
</tbody></table>
<br />
<b>December:</b><br />
The month which will stay in my heart forever for two extremely opposite feelings.<br />
Dec 5th - Left bangalore to Sankaran Kovil to attend my partner, friend, brother and gem of a person in my life's wedding.<br />
Dec 6th - First ritual [Panthakaal Naduvathu] & Dress Purchase [Usshhhsabba]<br />
Dec 11th - Engagement<br />
Dec 12th - Marriage<br />
Spent one full week with my beloved partner and witnessed one new relation joining hands with him in his life thereafter :)<br />
Went back home. Spent sometime with my family. My Sister scored 8.8 in her 7th Semester [Way higher than me] and made me happier than ever.<br />
The much need break of the year came to an end. Packed and back to bangalore.<br />
Dec 18th - Flew to mumbai for two weeks trip in Mumbai DevCenter<br />
Dec 19th - One of My uncles [He was almost my dad] passed away in an accident. So, flew back to bangalore on an emergency<br />
Dec 20th - The uncle's aunt [She was almost my mother] decided to joins hands with uncle in heaven. Worst way to end an year.<br />
Witnessed an awesome relation that existed in real continued to be so in heaven in just two days. <br />
The best love story I had ever seen in real. Some claimed that it was a foolish act but it was truely an act of proving togetheredness.<br />
They were so close to each other that one can't exist without the other. Hope their wishes will always be with me from heaven.<br />
Only Two people in my life who never knew what selfishness and jealousy was. We lost them.<br />
Two different events in subsequent weeks. Nothing to say but there's a lot to realize. <br />
<i>Bottom Line: This moment is not permanent. Loss is a part of life. Accept and go on. <br />
Everybody needs some spl care at some point in life, just spot it and help them to come out with glory [Dedicated to my sister :)]. </i><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-ShYWLXmS-8I/Ur2XkkNWnZI/AAAAAAAADcw/8hVvDEu5kgY/s1600/IMG_20131212_091802.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://3.bp.blogspot.com/-ShYWLXmS-8I/Ur2XkkNWnZI/AAAAAAAADcw/8hVvDEu5kgY/s320/IMG_20131212_091802.jpg" width="240" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Partner's Marriage</td></tr>
</tbody></table>
<br />
Although the year 2013 went ahead in a very much positive note from the beginning with small small obstacles financially and relation wise. <br />
In the end it left me with terrible and unmatchable loss of my second parents. <br />
More & More responsibilities over me. Time to become a man :)<br />
With their wishes let the forthcoming year be another milestone in my career and rejuvenate my family members from the loss.<br />
The year 2K13 was not all about work or the other way round even. There was a perfect balance in everything. Should thank my team at work and my family who helped me make this happen. Special thanks to My Dad, Roomies, Chandru, Durga and Jibin.</div>
Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-46248709402706793802013-06-28T16:18:00.000+05:302013-06-30T09:33:18.573+05:30GRUNT- The JavaScript Task RunnerGrunt helps developers automate the task of javascript deployment.<br />
In our development cycle, every javascript deployment used to be<br />
1. Code<br />
2. Minify<br />
3. Upload<br />
We were missing out two important phases which ensures code quality and reliability<br />
1. Lint<br />
2. Testing<br />
As our code became larger and larger, as anyother dev we also considered a refactor.<br />
The refactor resulted in splitting our large code base to manageable modules.<br />
Now, Deployment has to go through<br />
1. Unit test independent modules<br />
2. Merge Modules to a shippable target<br />
3. Lint<br />
4. Minify<br />
5. Deploy<br />
<b>Ooops... Nice but how?</b><br />
It's true that developers love things automated, and so we were. We arrived at a one stop solution GRUNT.<br />
<br />
This blog post is a <b>Let Them Know</b> Types. As, I felt that the instructions on grunt setup is kind of scattered :)<br />
To hav a better introduction with the hero, you should meet him at his <a href="http://gruntjs.com/">place</a><br />
Grunt has two parts:<br />
1. Using it<br />
2. Customizing it<br />
<br />
<b>How to start using it?</b><br />
<i>Installation:</i><br />
Grunt 0.4.x requires Node.js version >= 0.8.0. Install it from <a href="http://nodejs.org">here</a><br />
Read a bit on npm [Node Pacakge Manager] in case you are not aware of <a href="https://npmjs.org">here</a><br />
<pre class="brush:bash">$ npm install -g grunt-cli
</pre><b>What is grunt-cli?</b><br />
grunt-cli is a utility, that makes sure that it runs the grunt version installed locally to the project.<br />
This helps developers having different versions of grunt across projects.<br />
Installing grunt-cli adds "grunt" command to your system path<br />
<br />
<pre class="brush:bash">$ mkdir firstGruntProject
$ cd !$
$ grunt
grunt-cli: The grunt command line interface. (v0.1.9)
Fatal error: Unable to find local grunt.
If you're seeing this message, either a Gruntfile wasn't found or grunt
hasn't been installed locally to your project.
</pre><br />
<b>What does this mean?</b><br />
Basically to begin with a grunt task runner project, there are 3 important requirments.<br />
1. Local grunt module<br />
2. GruntConfig.js //Task runner's configuration<br />
3. package.json <br />
<br />
The above error states that we haven't got the local grunt module setup in our project home.<br />
Before doing that, lets set up a very basic grunt project.<br />
<br />
<b>Is there any easy way to generate basic grunt config file?</b><br />
Yes, check out <a href="http://gruntjs.com/project-scaffolding">Project Scaffolding</a><br />
There is a very handy utility <b>"grunt-init"</b>, which accepts a TEMPLATE to create a sample GruntConfig file or Grunt Plugin.<br />
A Template is kind of config file for automation of config or plugin creation.<br />
<br />
Sample Template for simple grunt project can be downloaded <a href="https://github.com/gruntjs/grunt-init-gruntfile">Grunt Git repo</a><br />
Once setup of template is done, install grunt-init globally<br />
<pre class="brush:bash">$ git clone https://github.com/gruntjs/grunt-init-gruntfile.git ~/.grunt-init/gruntfile
$ npm install -g grunt-init
$ cd firstGruntProject
$ grunt-init ~/.grunt-init/gruntfile
</pre>You will get a list of Yes or No's. Answer them and you are almost done to set up a grunt project<br />
<br />
<b>Next?</b><br />
We need a local grunt installation. It is as simple as that [npm install grunt@version]<br />
<pre class="brush:bash">$ npm install grunt
</pre>You can notice the absence of "-g" param for grunt install. <br />
This gives you an option of having multiple grunt versions across your projects. grunt-cli is the util which makes this possible.<br />
<br />
Lets try grunt now..<br />
<pre class="brush:bash">$ grunt
Loading "Gruntfile.js" tasks...ERROR
>> Error: Unable to read "package.json" file (Error code: ENOENT).
</pre>Ooops, Most of the gruntfile templates create a project specific package.json. But not in this sample template.<br />
So, Lets create our own using <b>npm init</b> command<br />
<pre class="brush:bash">$ npm init
</pre><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-EX7YhZju9Dc/Uc1pUaG3K1I/AAAAAAAABYo/IOKa1l_B-ZY/s1600/gruntconfig.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-EX7YhZju9Dc/Uc1pUaG3K1I/AAAAAAAABYo/IOKa1l_B-ZY/s320/gruntconfig.png" /></a></div><br />
<b>Ok, Is there a limitation on where the command should be run from?</b><br />
You can run "grunt" command from anywhere inside your project. <br />
"grunt" command is kind of nodejs require(). <br />
"grunt-cli" util takes care of locating the locally installed grunt module and load it with Gruntfile.js<br />
<br />
Once all this is done. Executing grunt should be as smooth as a cake provided there are no errors in the tasks and their internal confs.<br />
<br />
<b>Now how to install some packages I need?</b><br />
It is as simple as installing node packages<br />
<pre class="brush:bash">$npm install package@version --save-dev
</pre>**save-dev option rewrites package.json automagically.<br />
<br />
<b>How do I specify package specific configs?</b><br />
Mostly all modules have their wiki on how should you pass configs.<br />
Check <a href="http://gruntjs.com/sample-gruntfile">this</a> to get some more idea.<br />
<br />
Grunt provides lots and lots of apis. Check them out <a href="https://github.com/gruntjs/grunt/wiki#api">here</a><br />
I love grunt.option and grunt.file the most :)<br />
<br />
This is one part of the best parts. Grunt makes it possible for people to write their own tasks or plugins. We'll handle that in a separate blog post :)<br />
Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-86719154466770044672013-05-20T14:19:00.001+05:302013-06-30T09:32:57.270+05:30A Run for World without Leprosy - Run to remember<b>And My First 10K Marathon [<a href="http://www.procamrunning.in/tcsworld10k/">TCS World 10K</a>] - A run for world without leprosy</b><br />
<br />
Was yet another usual day to work post my work out session <b>@<a href="https://www.facebook.com/groups/musicandmetals/">Music&Metals</a></b>. Reached my workstation and booted my ubuntu to start with the proceedings of the day. The moment I logged in to my user, my mouse pointer rushed towards the Chrome Icon in unity launcher. Guess what? It's just to see if there are any updates in my FB home. And there it was, nice red color icon over the world of FB. It was a post from Dr. Manimozhi Natarajan, in our Gym's [Music & Metals] closed group. Urged to read what it is about, and it was an invite to all fiddles in M&M to participate in a 10K Marathon for a cause which was about to happen two week from then. And there you go.. I was realizing my wish to go for a long distance run coming true. And a pause [Ooops]. <br />
<br />
In my previous trip to our Mumbai Dev Center, I got to know that 4 of our team mates are participating in a 4*5Km relay and they are practicing for weeks to do well on the race day. I being with no practice in running and willing to complete 10K with ease?? Got to be kidding!! What next? I need practice!!, that too without a break [13 more days and you are at the start line]. I know me well, I'll give up very soon on things like these [after all I'm a human with laziness]. So, I badly wanted a partner who can give me a push whenever I get that feeling to stop. <br />
<br />
And there he is!! here comes my savior - Durga Prasad. My one and only companion in Bangalore team who also is interested in stuffs like this. I didn't resist to ask him for his wish. And he accepted without taking a moment to think. Just in 10 min after entering the office we got to leave to submit our application to AMICI [AIFO India's Center] and confirm our participation to Dr. Manimozhi. Dr. was so excited that he got such a quick response from his gym pals and it was like attending Kaun Banega Crorepati while filling down our application form.<br />
<br />
Dr. : Are you sure you wanna run 10K<br />
We : Yes<br />
Dr. : Odiduveengla pa? [Will you be able to finish?]<br />
We : Yes<br />
Dr. : Kashtamachae.. Idhukku munnadi odirukeengla? [Difficult it is. Have you got some experience?]<br />
We : No, but we'll practice<br />
Dr. : So, I'm locking yes. <br />
We : Yes<br />
Dr. : Computer Ji Lock Yes :P<br />
<br />
The next tough moment was, when they didn't accept the registration fee from us. They said that the organization will sponsor us. Oops now we have no other go. We didn't want to feel guilty for making someone pay our fee and in response we fail to make the finish line. So, the responsibility had been kept heavy on our shoulders. <br />
<br />
The next morning @5:30 my wake up alarm rang. I didn't wait for that 5 more min after an alarm, which gives you the best sleep in your life. Woke up immediately, prepared myself for the first day run. Meeting at Durga's place [near Leela palace] and completing the onward journey to inner ring road [3.76 Km] was the plan for day 1. Everything went fine till we realized that its time to start. We started our longest run till then [3.76Km, at least in my life]. We had to stop at 2 places just because we couldn't continue running. Terrified now. 12 more days, 7 more Kms without stop [Oops !!!]. We started preparing our mind now that we could make it. We just took the positives that happened on that day to get over the fear of failure :)<br />
<b>Day 2:</b> Same plan. 3.76 Km. Very glad news. We didn't stop :) Was so happy on that day. <i>Our mind accepted the challenge and it was ready</i>.<br />
<b>Day 3</b>: 4Km. Successful, No stop. <br />
<b>Day 4</b>: 6 Km with no stops but walking on every uphill [Good enough in first try] and we made it.<br />
<b>Day 5 to 8</b>: Thanks to CSK Match & weekends :P Both of us had plan to visit our home town and we had no other go, but to discontinue our practice [I continued my workouts, on Day 5 & 6]. Anyways Durga managed to continue it at his home town [Good job]. <br />
<b>Day 9</b>: 7.8 Km no stop [300m of walking alone]. I was not in this world when we reached that Domlur Flyover without a stop on our run towards home. We never believed that we would be able to make it. <br />
<b>Day 10</b>: Once again 7.8Km with no stop. Target achieved.<br />
<b>Day 11</b>: Drop in plan as we were very tired of 2 days of long distance running.<br />
<b>Day 12</b>: Just 4Km but fast running. Did at a better pace. But learnt what not to do on the race day [Don't start fast, if so you'll want to stop fast]. <br />
<b>Day 13</b>: Rest for the race day. <br />
<b>Day 14:</b> I reached the finish line in 1hr 2Min and my partner finished in 1hr 4min. Oh my goodness!!! We got medals :) Felt so happy that we made it and our practice made our lives easier. <br />
<br />
<b>Vote of Thanks:</b><br />
1. AIFO India [AMICI]: For giving me an opportunity to make our run meaningful and trusting us on our words :) Have decided to represent them in further marathons I might run in my life :) [Too Sentimental huh? :P] Also for the Reebok Tee I got on our pre-event gathering :P [Mr. Jose, Mr. Patrick, Dr. Mani, Mr. Jayanth, Dr. Prasad, Mr. Nyjil and other members of AIFO India]<br />
2. Dr. Manimozhi: Everything just happened was just because of him :) Will accompany you in your dream 10K run :P<br />
3. Jibin Kumar: For Music Metals and making the event memorable with a good bunch [10 - 5.7K runners] of participants. Anddd for the Briyani treat [with Supra] to celebrate the success @nandhini ;) :)<br />
<br />
<b>And Some Happy Moments:</b><br />
<a href="http://4.bp.blogspot.com/-6_AoHBUx1j8/UZiUeVjU2rI/AAAAAAAABUc/5UvQUhw5BWc/s1600/977066_4594183533368_1079416673_o.jpg" imageanchor="1" ><img border="0" src="http://4.bp.blogspot.com/-6_AoHBUx1j8/UZiUeVjU2rI/AAAAAAAABUc/5UvQUhw5BWc/s320/977066_4594183533368_1079416673_o.jpg" /></a><a href="http://2.bp.blogspot.com/-HLM0xxBphxA/UZjRzIeQv6I/AAAAAAAABV4/Hzd_RGz32TA/s1600/Timing.png" imageanchor="1" ><img border="0" src="http://2.bp.blogspot.com/-HLM0xxBphxA/UZjRzIeQv6I/AAAAAAAABV4/Hzd_RGz32TA/s320/Timing.png" /></a><a href="http://2.bp.blogspot.com/-5_nAMUSfDjU/UZjGO882ikI/AAAAAAAABVo/cW6QZk-tRu4/s1600/922458_4594877150708_785577484_o.jpg" imageanchor="1" ><img border="0" src="http://2.bp.blogspot.com/-5_nAMUSfDjU/UZjGO882ikI/AAAAAAAABVo/cW6QZk-tRu4/s320/922458_4594877150708_785577484_o.jpg" /></a><a href="http://1.bp.blogspot.com/--vaq0JAqyP4/UZnz02IYvbI/AAAAAAAABWg/IW1vqpqJC2g/s1600/965004_4594398378739_1272556509_o.jpg" imageanchor="1" ><img border="0" src="http://1.bp.blogspot.com/--vaq0JAqyP4/UZnz02IYvbI/AAAAAAAABWg/IW1vqpqJC2g/s320/965004_4594398378739_1272556509_o.jpg" /></a><br />
<a href="http://3.bp.blogspot.com/-51KLLMqQPjc/UZ8gVhq2tOI/AAAAAAAABXk/dCsT1F1U7xA/s1600/FcertA4.tmpl-1.jpeg" imageanchor="1" ><img border="0" src="http://3.bp.blogspot.com/-51KLLMqQPjc/UZ8gVhq2tOI/AAAAAAAABXk/dCsT1F1U7xA/s320/FcertA4.tmpl-1.jpeg" /></a><br />
<br />
This post might be tooooo much for just a marathon finish.. But First - always is special and it is good to register the moment :)<br />
If your mind believes, your body assists with an ease :) Push.. Push.. Push..<br />
Our Next Target: On June 9th..Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-64747627000395842292013-02-06T12:37:00.001+05:302014-10-08T16:14:40.670+05:30Headless Chrome/Firefox Selenium Java in Amazon EC2Setting up chrome/firefox in linux based x86_64 EC2 instance<br />
In this post we'll see how to setup chrome/firefox in EC2 instance.<br />
Further we'll discuss the way to setup chromedriver with selenium [java] in EC2 instance aswell.<br />
<b>Why is that difficult?</b><br />
Linux based EC2 instances <i>lack gtk+</i>, which is a must to launch any GUI enabled applications.<br />
<br />
<b>How to solve?</b><br />
Compile gtk+ from source. <br />
<a href="https://gist.github.com/joekiller/4144838" target="_blank">This gist by joekiller</a> has the complete dependency tree resolved for installing gtk+ for x86_64 machines.<br />
<a href="https://gist.github.com/joekiller/4144838#file-gtk-firefox-sh-L77" target="_blank">Line 77</a> Basically installs firefox from its tarball. You can comment it out incase if you don't wish to.<br />
Incase <a href="https://gist.github.com/joekiller/4144838#file-gtk-firefox-sh-L42" target="_blank">Line 42</a> fails. Do a wget for direct tarball from <a href="http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest/linux-x86_64/en-US/" target="_blank">here</a>, instead the complex recursive wget. <br />
For Ex: <br />
<pre class="brush:bash">wget http://releases.mozilla.org/pub/mozilla.org/firefox/releases/latest/linux-x86_64/en-US/firefox-18.0.2.tar.bz2
</pre><b>So, All done?</b><br />
Nopes, Now we can't run either of the browsers as we lack <i>X11 server</i> which does graphics operations & screen outputing. <br />
As our environment is headless we can't go for real X11 server as well [lack of hardware units to do screen outputing].<br />
<br />
<b>How do we solve this?</b><br />
We need <a href="http://en.wikipedia.org/wiki/Xvfb" target="_blank">Xvfb</a> setup in our instance.<br />
<pre class="brush:bash">$ yum install Xvfb
$ Xvfb :1 -screen 0 1280x768x24 &
#starts Xvfb in display ":1"
</pre>Should start a X virtual frame buffer (Xvfb) which performs all graphics operation in memory.<br />
<br />
<b>All set?</b><br />
Not really :P Still we haven't configured the instance to use display ":1" for graphics operations.<br />
We can do it by<br />
<pre class="brush:bash">$ export DISPLAY=:1
</pre>Executing the above will remain for the session that user has logged in [similar to standard linux terminal session].<br />
You can even edit the bashrc profile. But it might need a instance restart to take effect [Not very sure].<br />
<br />
<b>Problem 2:</b><br />
Setting up chromedriver[java] isn't a tough task incase you landed in here first :D<br />
<br />
<b>Step:1</b><br />
Install chrome binary from the source or add the source urls of centos to amzn repo and do a yum install<br />
Note: Chrome will refuse to start as root. So make sure your <i>java process will be running as non root profile</i>.<br />
<pre class="brush:bash">[root@xyz chrome]$ google-chrome
Xlib: extension "RANDR" missing on display ":1.0".
[9706:9706:0206/061403:ERROR:chrome_browser_main_extra_parts_gtk.cc(51)] Startup refusing to run as root.
</pre><b>Step:2</b><br />
Setting up the display is necessary to make chrome to use Xvfb for graphics operations<br />
<pre class="brush:bash">$ vim /usr/bin/google-chrome
#add export DISPLAY=:1 to the beginning of the script
</pre><b>Step:3</b><br />
Download the appropriate driver from <a href="http://code.google.com/p/chromedriver/downloads/list" target="_blank">code.google.com</a><br />
Locate it in a directory which can be accessed without root permissions<br />
<br />
<b>Step:4</b><br />
See the sample tutorial @<a href="http://code.google.com/p/selenium/wiki/ChromeDriver">Chrome Selenium Binding</a><br />
Below I'm highlighting the important config code from the same link.<br />
<pre class="brush:java">service = new ChromeDriverService.Builder()
.usingChromeDriverExecutable(new File("path/to/my/chromedriver")) //location of the driver you downloaded
.usingAnyFreePort()
.build();
</pre><b>Step:5</b><br />
Start the java process [non-root] you might see some c errors. Ignore them unless your process contiues to run.<br />
Monitor the status of chromedriver.log [In our system it is located in /opt directory].<br />
Make sure there are no "Connection Refused" or "ShutDown" messages. <br />
These errors will eventually throw an exception at java main thread as TimedOutException.<br />
Then main thread will exit.<br />
<br />
As a whole<br />
<pre class="brush:bash">$ wget "https://gist.github.com/joekiller/4144838/raw/1560dbcf05cd90ba1052e8d999007f8803778c4a/gtk-firefox.sh"
#remember to comment line 77 incase u don't need firefox
$ chmod 777 gtk-firefox.sh
$ sh gtk-firefox.sh
#above command will take atleast 30 min
$ yum install Xvfb
$ Xvfb :1 -screen 0 1280x768x24 &
#install google-chrome via yum [add source urls to repo] or from source
$ google-chrome
#make sure the command doesn't exit till you force it to [no gtk fatal errors or permission issues]
$ which google-chrome
$ /usr/bin/google-chrome
$ vim /usr/bin/google-chrome
# add export DISPLAY=:1
# run the java code it should work
</pre>If you face any issues leave a comment will see if I could help.<br />
Hope this helps :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com1tag:blogger.com,1999:blog-4836497234580815703.post-82964790539238780862012-12-25T14:17:00.000+05:302013-06-30T09:32:44.491+05:30Backbone JS + Chrome App [manifest version 2]Hello World!!, YAJSBP :)<br />
<b>QUOTE:</b> Getting to know a library or a technology is pretty easy, but things get reversed when you want to apply the same which you felt you knew :)<br />
In this blog post I'll take you through some integration challenges I faced while developing a chrome app along with backbonejs<br />
<br />
So, I got to know about this guy Backbone.js an year before at jsFoo 2011.<br />
The moment I noticed him, I visited his <a href="http://backbonejs.org/">birthplace</a> and got an overview of him.<br />
Then I felt that I could claim I know backbone.js. Later realised it was too early to say that.<br />
An year after I decided to try this guy and started developing a chrome app[<a href="https://github.com/tamilmani58/jus4friendzz" target="_blank">Features Recorder</a>].<br />
Then I faced the following small challenges[on integerating backbone with chrome app] which I solved my own way :P<br />
<br />
<b>Problem: 1</b> Chrome App manifest version 2 doesn't allow <b>eval</b> or <b>new Function</b><br />
<b>Error: Uncaught Error: Code generation from strings disallowed for this context</b><br />
Take a look at <a href="http://developer.chrome.com/extensions/contentSecurityPolicy.html">Chrome app Content Security Policy</a><br />
<br />
<b>Why do we need this?</b><br />
<a href="http://underscorejs.org/underscore.js">Underscore.js</a> microtemplating uses <b> new Function </b> syntax for compiling the templates<br />
Note: The problem might persist with other templating options too<br />
<br />
<b>Solutions:</b><br />
1. As mentioned in the CSP page, relax the rule against eval and related functions<br />
<pre class="brush:plain">"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
</pre>2. As I just used underscore.js microtemplates. I pre-compiled my templates offline [not in the app]<br />
<pre class="brush:javascript">var source = _.template("My template code").source
//assigned the source to template property of the view
//This solved the problem
//Ex:
Backbone.View.extend({
initialize: function () {},
template : function(obj){ //Precompiled template code
var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};
with(obj||{}){
__p+='<a href="#"><i class="icon-chevron-right"></i>'+
((__t=( title ))==null?'':__t)+
'</a>';
}
return __p;
}
});
</pre>3. Refer <a target="_blank" href="http://matthewrobertson.org/blog/2012/07/10/javascript-templates-and-chromes-content-security-policy/">this blog</a><br />
<br />
<b>Problem: 2</b> window.localStorage for offline packaged is disabled<br />
<b>Problem: 3</b> <a href="http://developer.chrome.com/extensions/storage.html">chrome.storage</a> is asynchronous [get & put are async as ajax]<br />
<br />
<b>Error: "window.localStorage is not available in packaged apps. Use chrome.storage.local instead."</b><br />
I planned to build a offline packaged app. <br />
But this error stunned me up as I can no more use <a href="http://backbonejs.org/docs/backbone-localstorage.html">local storage adapter for backbone</a><br />
<br />
<b>Solution:</b><br />
I built my own <a href="https://github.com/tamilmani58/jus4friendzz/blob/master/backbonejs.chromeStorage.js">localstorage adapter</a> for chrome.storage<br />
As the storage works in async way, callbacks for functions like model.save and create remained a must<br />
<pre class="brush:javascript">var options = {success: function () { }};
model.save(options);
</pre>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-67761976512607159812012-11-29T18:33:00.000+05:302013-06-30T09:33:54.244+05:30Asynchronous Javascript & jQuery Deferred Why?Using jQuery Deferred<br />
In this post I'll try to cover an overview of promises and deferred. Further how to use them in nodejs.<br />
<br />
<b>Define Deferred?</b><br />
Google Define: Put off (an action or event) to a later time; postpone<br />
<br />
<b>Deferred in javascript?</b><br />
Javsacript being an event driven scripting [and a developing programming] language, there is obvious need for developers to defer things awaiting events.<br />
For ex:<br />
<pre class="brush:javascript">window.addEventListner("load", function () { console.log("Defer my execution till window load"); }, false);
$.ajax({ url: 'data.html',
success: function () {
console.log("Defer my execution till ajax load is successful")
},
error: function () {
console.log("Defer my execution till ajax load fails")
}
});
</pre><br />
<b>So? This is nothing unusual!!!</b><br />
Ya, obviously it is nothing unusual and obviously a beginner level fact.<br />
Deferred: As a programming paradigm, is a design pattern which solves the problem of code neatness and maintainability while travelling along the lane of languages like javascript.<br />
<br />
<b>Why code neatness gets spoiled?</b><br />
3 Basic Scenarios on which <b><i>I feel so :D</i></b> are<br />
1. Duplicate code on either success or error callbacks [Ex: Hiding the loader animation in ajax]<br />
2. Start a deferred event after success of another deferred event [Means: Call backs inside Call backs inside .. recursion :P]<br />
3. Awaiting multiple events to complete successfully to proceed with someother execution [Ex: Submit button clicked, Animation Completed, Validation Done -> Proceed to Sign UP]<br />
<br />
Beginner's Solution for all the above:<br />
<br />
<b>Scenario:1</b><br />
<pre class="brush:javascript">//Assume the beginner knows a bit of refactoring :P
function common() {
//Common Function after ajax call
}
$.ajax({ url: 'data.html',
success: function (data) {
common();
console.log("Defer my execution till ajax load is successful")
},
error: function (data) {
common();
console.log("Defer my execution till ajax load fails")
}
});
</pre><br />
<b>Scenario:2</b><br />
<pre class="brush:javascript">$.ajax({ url: 'data.html',
success: function (data) {
$.ajax({ url: 'data1.html',
data: data,
success: function (data1) {
$.ajax( ..... //so on and it is enough :P
}
});
}
});
</pre><br />
<b>Scenario:3</b><br />
<pre class="brush:javascript">//I Couldn't think of any better worse code sample :P
var i = 0;
function incr() {
i++;
if( i == 2 ) {
doSubmitForm();
}
}
$("submit-button").on('click', fuction () {
//do some validation and increment a global var
});
$("submit-button").on('click', function () {
//do some animation and increment a global var
});
</pre><br />
And Hence we are done with code samples. Now lets go with Deferred and solve all the above 3<br />
<br />
<b>Scenario:1</b><br />
<pre class="brush:javascript">var ajaxCall = $.ajax(myResourceURL); // Returns a deferred
ajaxCall.done(function () { /* Call me on success */ });
ajaxCall.fail(function () { /* Call me on success */ });
ajaxCall.always(function () { /* Call me always. Plz shut the loader div :P */ });
</pre><br />
<b>Scenario:2</b><br />
<pre class="brush:javascript">var one = $.ajax( url ),
two = one.pipe(function( data ) {
return $.ajax( url2, {data: data} );
}),
three = two.pipe(function( data ) {
return $.ajax( url3, { data: { data: data } } );
});
three.done(function( data ) {
// data retrieved from url2 as provided by the first request
});
</pre><br />
<b>Scenario:3</b><br />
<pre class="brush:javascript">var validate = new $.Deferred(),
animate = new $.Deferred(),
proceed;
validate.done(function () { });
animate.done(function () { });
proceed = $.when(validate, animate)
.then(proceedSubmit, dont, notifySomething);
$("submit-button").on('click', function () { /*do some validation and you can even reject*/ validate.resolve(); });
$("submit-button").on('click', function () { /*do some animation and resolve or reject */ animate.resolve(); });
</pre><br />
<b>PS:</b> Refer <a href="http://api.jquery.com/jQuery.when/">when</a>, <a href="http://api.jquery.com/deferred.pipe/">pipe</a> and <a href="http://api.jquery.com/deferred.then/">then</a><br />
<b>Note:</b><br />
1. How does promise differ from deferred?<br />
Promise can't be resolved or rejected by another source. But deffered can be. [Ex: In listing 3 validate and animate are resolved from click event's callback]<br />
2. How do I pass params to done, fail, always callbacks or change the context of execution?<br />
Check <a href="http://api.jquery.com/deferred.resolveWith/">resolveWith</a> and <a href="http://api.jquery.com/deferred.rejectWith/">rejectWith</a><br />
Also you can do deferred.resolve.call(context, param1, param2,...) incase you wanna get rid of array processing<br />
3. Are we by any chance restricted to one call back per promise or deferred state (done, fail, always)?<br />
Nopes (at least in jQuery deferred) you can add as many listeners [same as event listeners] for any of the promise states. All such callbacks will be triggered when promise gets resolved to appropriate state. This feature makes really good point in decoupling the actions we use to do in only available success or error callback in response to an event [like ajax load].<br />
4. What if I attach a callback for a deferred which is already resolved?<br />
The callback will be triggered immediately after the attachment, provided the state of the promise matches.<br />
<br />
Lets see the way we can use jQuery deferred in nodejs<br />
As mentioned in the Note 1: We can't use promise in node unless the module supports resolve & reject with in itself<br />
<pre class="brush:javascript">var $ = require('jquery'),
fileDeferred = new $.Deferred(),
fs = require('fs');
fileDeferred.done(function (data) { });
fileDeferred.fail(funtion (err) { });
fileDeferred.always(function () { });
fs.readFile(filename, 'utf8', function (err, data) {
if(err) {
fileDeferred.reject.call(null, err);
} else {
fileDeferred.resolve.call(null, data);
}
});
</pre>If you do lots async programming do consider having a look at <a href="https://github.com/caolan/async">asyncjs</a><br />
I hope you will be able to see the difference in normal way of programming than deferred way. Also how deferred way helps you to maintain code neatness. If you don't program the deferred way, I think its time to give it a try :)<br />
Loads of thanks to @trevorburnham for <a href="https://leanpub.com/asyncjs"> Async Javascript </a><br />
This blog is almost a gist of what I learnt from his creation :)<br />
I hope I did some justice and helped you understanding the need for deferred.Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-35394840406921671742012-10-02T14:20:00.000+05:302012-10-03T15:03:17.427+05:30Cassandra Composite Types - A Overview [with CQL & Cassandra-Cli examples]Just felt like sharing what is composite type in cassandra and How can we make use of it<br />
After so many discussions in Stackoverflow and PHPCassa forums, I hope I have got a clear picture over the topic<br />
<br />
<b>What are composite types?</b><br />
Composite types are like structures in C or C++<br />
<br />
<b>For ex:</b><br />
The way we define a linked list [basic]<br />
<pre class="brush:cpp">struct LLNode {
int data;
char name[20];
struct LLNode *next;
}
</pre>Which means every member of this struct will have data of type int, name of type char array and a next pointer of type LLnode<br />
The struct is a composite of basic datatypes[not exactly in this case] <br />
Also you can't initialize value to any of these attributes when you define a struct<br />
<br />
The same way <i>Cassandra Composite Type is a dataType derived from existing basic supported dataTypes</i>.<br />
<br />
<b>Why do we need this?</b><br />
Cassandra initially had and still has the concept of super columns. <br />
The basic use of them is maintaining an <i><a href="http://en.wikipedia.org/wiki/Inverted_index">inverted index</a></i>. <br />
<br />
Consider a data model in cassandra<br />
<pre class="brush:plain">ColumnFamily: UserMaster
ColumnModel:
userID: {name, prevCompany, experience}
</pre>Now incase we need to support a query <br />
<br />
<b>Select name from UserMaster where prevCompany = xyz;</b><br />
<br />
This is totally impossible untill we have a secondary index created.<br />
<br />
To overcome this issue, Cassandra gave developers an option of creating their own index using super columns<br />
<pre class="brush:plain">ColumnFamily: UserIndex
ColumnModel:
Date: {company1: {rowID1, .. , rowIDN },..,companyN: {rowID1, .. , rowIDN } } //SuperColumn
</pre><br />
Now we can answer the above query via<br />
<pre class="brush:plain">allUsers = UserIndex[Date][prevCompany];
for i in allUsers
echo UserMaster[i][name];
</pre><br />
But this is a bit messy as every insert leads to two inserts with no transactional guarentees.<br />
Also every read will result in minimum two reads across CFs<br />
<b>Also What if we have one more column of interest????</b><br />
Say <br />
<b>Select name from UserMaster where prevCompany = xyz and experience = 2yrs; </b><br />
And There are many other issues with super column itself<br />
<br />
To overcome this [inverted index] EdAnuff came up with the concept of composite types<br />
<br />
<b>How would composite types save time?</b><br />
Point to remember:<br />
1. Composite types are type preserved<br />
Ex: <br />
CompositeType(ascii, int, ascii);<br />
a:1:user1<br />
a:10:user2<br />
aa:2:user1<br />
ab:0:user2<br />
<br />
You can see the columns sorted first based on component 1, then 2 and then 3; <br />
And sorting is based on the exact type of the component<br />
<br />
So, we model our data in the following way<br />
<pre class="brush:plain">ColumnFamily: UserMaster
ColumnModel:
rowID: {prevCompany:exp:userName} //Notice the column value in model 1 becomes the Column names
</pre><br />
<b>Sample:</b><br />
20120901: {prevCompany1:2:user1 => {null}, prevCompany1:2:user2 => {null}, prevCompany1:3:user3 => {null}, ...}<br />
<b>Query:</b><br />
select * from UserMaster where prevCompany = 'prevCompany1' and exp > 2<br />
<b>Result:</b><br />
prevCompany1:3:user3 => ''<br />
<br />
<b>Note: </b><br />
I have kept the column value null as we don't need anything in there.<br />
Also I have kept user ID as the last component because our read pattern is<br />
Given <b> a company </b> get all users with given <b> experience range </b><br />
<br />
Now we can query for <br />
All employees whose prevCompany is 'x'<br />
All employees whose prevCompany is 'x' and exp is > '2yrs'<br />
All employees whose prevCompany is 'x' and exp is = '2yrs' and name = 'xyz'<br />
and so on<br />
<br />
<b>Note:</b><br />
Your query should always fetch a contiguous slice incase of composite types<br />
<br />
<b>Means:</b><br />
<i>Sample Data [assume]:</i><br />
20120901: {y:2:123, y:2:124, y:2:125, y:3:123, y:3:126}<br />
<br />
All employees whose prevCompany is 'y' and exp is >= '2yrs' and userName = '123' will not work<br />
Why?<br />
Filter1: prevCompany is 'y' => contiguous<br />
{<b>y:2:123, y:2:124, y:2:125, y:3:123, y:3:126</b>}<br />
Filter2: exp is >= 2yrs => still contiguous<br />
{<b>y:2:123, y:2:124, y:2:125, y:3:123, y:3:126</b>}<br />
Filter3: userID = '123' => non contiguous<br />
{<b>y:2:123</b>, y:2:124, y:2:125, <b>y:3:123</b>, y:3:126}<br />
<br />
All employees whose prevCompany is 'y' and exp is = '2yrs' and userName > '123' will work<br />
Why?<br />
Filter1: prevCompany is 'y' => contiguous<br />
{<b>y:2:123, y:2:124, y:2:125, y:3:123, y:3:126</b>}<br />
Filter2: exp is = 2yrs => still contiguous<br />
{<b>y:2:123, y:2:124, y:2:125</b>, y:3:123, y:3:126}<br />
Filter3: userID > '123' => still contiguous<br />
{y:2:123,<b> y:2:124, y:2:125</b>, y:3:123, y:3:126}<br />
<br />
Finally,<br />
Composite Types in cassandra is a nice concept but limits the number of components while defining the columnfamily<br />
Cassandra has support for Dynamic Composite Columns [to overcome previous issue] but as of me it is not safe [as type safety is the tradeoff]<br />
Syntax to Create composite type via cassandra-cli<br />
<pre class="brush:sql">create column family TestComposite
with comparator='CompositeType(UTF8Type, UTF8Type, LongType)'
and key_validation_class = 'UTF8Type',
and defaut_validation_class = 'UTF8Type';
</pre>Remember you can't query composite types via cassandra-cli [unless a point query]<br />
<br />
Syntax to create composite type via CQL<br />
<pre class="brush:sql">CREATE TABLE UserMaster (
day ascii,
preCompany ascii,
experience int,
userName ascii,
PRIMARY KEY (ID, preCompany, experience, userName)
);
</pre><b> You can always only query based on components listed in Primary Key field above </b><br />
Check this <a href="http://stackoverflow.com/questions/12297841/cassandra-1-1-composite-keys-columns-and-filtering-in-cql-3/">post in SO</a><br />
Specifying composite fields via CQL is a bit different <a href="http://www.datastax.com/docs/1.1/ddl/column_family#composite-columns">check this detailed post</a> to get a clear picture. Remember both ways use the same storage pattern<br />
<br />
Hope the whole blogpost made some sense about composite columnsTamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-91377258096208294162012-07-27T15:58:00.001+05:302012-07-27T16:09:54.150+05:30Varnish Cache Purge, Ban and Ban LurkerLets walk through some basics of varnish before understanding purge and ban<br />
<br />
<b>Varnish?</b><br />
From <a href="https://www.varnish-cache.org/">DOC</a>: Varnish is a web application accelarator.<br />
Varnish can cache & serve all your static properties [css, js, images, parsed PHP pages, HTML]<br />
Reduces load on the webservers even on high traffic.<br />
Can act as a load balancer even [provided with proper director configurations].<br />
<br />
Varnish uses VCL <b>[Varnish Configuration Language]</b> to override the defaults and tweak varnish based on usecase<br />
<br />
Varnish caches contents [cache object] against a key.<br />
By Default the key is Hash(HostName and Request URL)<br />
We can override the defaults by editing <b>vcl_hash</b> sub-routine in vcl file<br />
<br />
<b>Do Cache objects live long in varnish?</b><br />
In varnish every cache object is stored against a ttl value.<br />
Every object will be auto-magically removed out of cache once they reach the expiry.<br />
TTL can be configured globally as default while starting <b>varnishd with -t option</b>.<br />
Also can be overridden in VCL using <b>bresp.ttl value</b>.<br />
<br />
<b>What if I had to manually invalidate a cache object?</b><br />
There comes purge and ban as savior :)<br />
<br />
<b>Purge?</b><br />
Invalidates [removes] specified cache object actively.<br />
<i>Method?</i><br />
CURL -X "PURGE" url<br />
<i>Means?</i><br />
Hit varnish with request method as purge. You can use any equivalent of CURL<br />
<i>Can anybody purge my contents?</i><br />
Use <b> acl purge {} </b> directive to allow IPs/IP Class from which purge request can be sent.<br />
<br />
<b>BAN?</b><br />
Invalidates cache objects passively. Supports regex.<br />
Consider ban as a filter over already available cache objects.<br />
<i>Method?</i><br />
ban req.http.host == "example.com" && req.url ~ "\.png$"<br />
<i>Means?</i><br />
filter all png objects from example.com<br />
The above code should be placed in vcl_recv<br />
Authentication mechanism is same as purge<br />
<br />
<b>Purge vs Ban How do they differ?</b><br />
<b>Purge:</b><br />
Invalidates cached object actively [sets the ttl of object to 0 and removes the moment purge request is sent]<br />
<b>Ban :</b> <br />
A ban is a filter maintained by varnish not a command.<br />
It is always applied before delivering an object from the cache.<br />
There might be multiple bans in the same varnish instance. <br />
A ban is applicable only for the contents that were present by the time it was created.<br />
It will never prevent new objects being cached or delivered.<br />
Too many ban lists per instance will consume too much cpu.<br />
Long lived cache [assume infinite TTL] objects with no hits will remain untouched by bans and consumes memory.<br />
<br />
<b>Why CPU & Memory consuming?</b><br />
Every request before being served it might need to be matched across <b>multiple ban list</b> before deliver.<br />
Matching here means a regex match. Hence It is going to consume CPU.<br />
Consider heavy traffic systems. The frequency of requests to ban fiter check might be a concern.<br />
Ban is clearly a filter. <br />
It will take care of removing objects that are actively getting hits and that match ban list.<br />
But it will not take care of idle cache objects with high TTL values even if they match the ban.<br />
Hence, the memory consumed by them is never released till their TTL expires although we had already invalidated them.<br />
<br />
<b>How to overcome this?</b><br />
Use Ban Lurker.<br />
<br />
<b>What problem does this solve?</b><br />
1. Banned objects can be discarded in background. <br />
2. The size ban-list can be reduced.<br />
Ban Lurker is a varnish process who will be actively walking the cache and invalidate objects against the ban list.<br />
This is a kind of enable/disable feature by default off [enable it: param.set ban_lurker_sleep 0.1].<br />
Read more about ban lurker <a href="https://www.varnish-software.com/blog/ban-lurker">here</a><br />
<br />
<b>Final Point:</b><br />
Purge will not refresh the invalidated object from backend. It will happen only in next cache miss.<br />
Incase you want to force a cache miss and refresh content from backend you need to set<br />
<b>req.hash_always_miss to true</b><br />
In that cache varnish will miss the current object in the cache, thus forcing a fetch from the backendTamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-77939592031554856912012-07-11T19:25:00.000+05:302012-08-06T19:32:47.076+05:30npm - package manager for node and package.json a overviewnpm: node package manager [!an acronym :P]<br />
<br />
Till the time I got to know about this guy, code upload across servers use to be a tough task.<br />
He is the one to look out incase you are to develop an application in node and host it across servers<br />
<b>package.json</b> is his weapon ;)<br />
In this article I'm just planning to touch npm basics and use of package.json and it is tl;dr ;)<br />
<br />
<b>What is npm?</b><br />
From <a href="http://npmjs.org"> here </a>: <i> npm is a package manager for node. You can use it to install and publish your node programs. It manages dependencies and does other cool stuff. </i><br />
Basically node uses commonjs style module system. <br />
Every module is an independent piece of javascript code which can be plugged in and out of the core of your application. <br />
Modules can be custom built or built for a generic purpose like redis, mysql, async, log4js. <br />
And it will be always good to know if there are any pre-built modules available for our need before we start building our own. <br />
npm does it for you like a charm :)<br />
<br />
<b>How do I install npm?</b><br />
npm by default is shipped along with node. <br />
So, zero step installation.<br />
<pre class="brush:bash">sudo apt-get install node
npm help
</pre>To search for a package. Just emit the following command<br />
Ex:<br />
<pre class="brush:bash">#npm search keywords
npm search redis
</pre>Locate yours and install it via<br />
<pre class="brush:bash">npm install pacakage-name
</pre><b>Where will my installed packages go?</b><br />
npm installation can be done in two modes local [Default] or global<br />
<b>Local:</b><br />
npm install redis would follow<br />
<pre class="brush:plain">if(cwd == node_modules)
install in ./redis directory
else
install in ./node_modules/redis directory
</pre><b>Global:</b><br />
<pre class="brush:plain">npm install -g redis would follow
prefix/lib/node_modules
</pre><b>So, That is it?</b><br />
Wait we still have our main picture :) <b> npm help or npm help action </b> would help a lot<br />
<br />
<b>package.json => It should be a pure json not a javascript object</b><br />
Actually package.json has many many many options. <br />
I suggest to have <b> npm help json </b> or <a href='http://package.json.jit.su/'>this as a reference</a><br />
Check out <a href='https://github.com/mranney/node_redis/blob/master/package.json'>node_redis</a>, <a href="https://github.com/caolan/async/blob/master/package.json">async</a><br />
<br />
Let us consider async's package.json for example<br />
<pre class="brush:javascript;">{ "name": "async"
, "description": "Higher-order functions and common patterns for asynchronous code"
, "main": "./index"
, "author": "Caolan McMahon"
, "version": "0.1.22"
, "repository" :
{ "type" : "git"
, "url" : "http://github.com/caolan/async.git"
}
, "bugs" : { "url" : "http://github.com/caolan/async/issues" }
, "licenses" :
[ { "type" : "MIT"
, "url" : "http://github.com/caolan/async/raw/master/LICENSE"
}
]
, "devDependencies":
{ "nodeunit": ">0.0.0"
, "uglify-js": "1.2.x"
, "nodelint": ">0.0.0"
}
}</pre><br />
<b>Try</b><br />
<pre class="brush:plain">npm search async
NAME(name) DESCRIPTION(description) AUTHOR(author) DATE KEYWORDS(keywords)
async Higher-order functions and common patterns for asynchronous code =caolan 2012-07-03 12:17
</pre><br />
Some important canditates I use:<br />
<pre class="brush:plain">"name" => unique & represents your module in npm global repo
"devDependencies" => Will only be installed iff "npm install --dev" is done
"repository" => Where to look for the source code of your module? incase of a npm published module
"version" => Very important param. Should be in x.y.z format. Used in the hash to locate your module in global node repo.
"dependencies" => What are all the modules do your module depends on?
"scripts" => "start" => what should happen when you hit "npm start" on your application folder
=> "test" => what should happen when you hit "npm test" on your application folder
</pre>[Check <a href="http://howtonode.org/introduction-to-npm"> Acquiring Fame </a>]<br />
<br />
<b>Why dependencies?</b><br />
Basically any modules we use in an application would have dependencies itself<br />
<b>For ex:</b> node_redis has hiredis dependency<br />
<br />
It will be difficult for a programmer as such to resolve those dependencies manually<br />
Hence to make our life easier, on<br />
npm install redis<br />
npm will pick up the internal dependencies of a module from its package.json and will manage to resolve them.<br />
This process continues until the dependency tree is satisfied [means recursively].<br />
Check out this <a href="http://stackoverflow.com/questions/11343419/node-js-elementtree-required-get-cannot-find-module-sax/11344843#11344843">SO</a> post :)<br />
<br />
<b>Why scripts => start/test?</b><br />
We follow different procedures on deployment of different services<br />
<b>For Ex:</b><br />
nohup node index.js &<br />
forever start index.js<br />
node index.js<br />
Hence it would be hard to remember which matches to what?<br />
So, specifying the start up script in your package.json will make your life as much easier as this<br />
<b>npm start</b><br />
The same applies for test.<br />
Hence the command to start a node application will be the same across your environment <br />
<br />
<b>Why version?</b><br />
npm indexes your module based on hash of (name + version) inorder to resolve version based dependencies<br />
For Ex:<br />
In dependencies section I can specify<br />
"*" => anything is ok for me<br />
">0.6.7" => anything > than 0.6.7 is ok for me<br />
"~0.6.0" => anything > 0.6.0 and < 0.6.x is ok for me
"0.6.7" => I need 0.6.7<br />
So, to handle all such dependencies npm indexes the version along with name of the module<br />
<br />
<b>How do we build our projects?</b><br />
Basically we rely on dependencies attribute much. <br />
The local node framework we had designed for our system allows developers to work independently on their module.<br />
Modules people work on is hosted independently on git and they are just added as dependencies in package.json of the whole application.<br />
For deployment we just push the package.json to our servers and run <br />
<b>npm install && npm run :)</b><br />
All our developers' custom built modules [from git] and their internally dependencies [from npm global] are resolved recursively by npm<br />
So, we hardly push any code to live servers. npm takes care of building the whole application in no time :)<br />
Uploading code with resolved dependencies is hell lot of code and binaries. <br />
Sometimes modules can have compile environment dependencies. <br />
Also our modules internally have dependency to different versions of same module. So, we didn't want to go with global installation once.<br />
Every local module get their dependencies resolved at their level. Hence no need to worry about version clash. [We optimize our package.json a bit though]<br />
So, we left it to npm + package.json to do our task :P They are doing a really great job :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-582785696592272132012-05-09T16:09:00.002+05:302012-05-11T23:53:37.065+05:30Javascript - A Reference for Beginners<h3>Javascript Resources for beginners</h3><a href="http://ecma262-5.com/ELS5_HTML.htm"> Javascript </a> is one of the best programming languages that I had come across as a programmer<br />
Once I got a chance to know the good parts of javascript from <a href="http.crockford.com">Crockford</a> from this <a href="https://www.youtube.com/watch?v=hQVTIJBZook"> video </a><br />
I got some interest in exploring all that good parts in full.<br />
First thing that impressed me from Crockford's presentation was<br />
"Javascript is the only programming language which people dare to use before learning it"<br />
Till that point I belonged to the same category that Crockford mentioned in the above quote<br />
<br />
So, I began to spend some valuable time with the language to come out of that crowd<br />
<br />
As a first thing I read a really nice book <a href="http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273"> <b> "Pro Javascript Techniques" </b> </a><br />
Then, I got a chance to attend a javascript conference <b> jsFoo </b> organised by <a href="http://hasgeek.com/"> HasGeek </a><br />
There were really nice and lightning talks on advanced javascript techniques in which I had no knowledge about till that point.<br />
I just observed the talks and grasped as much as I could.<br />
<br />
After the day 1 of that conference my exploration on javascript techniques started.<br />
Let me take you through the resources which gave me a clear picture on javascript and its awesome parts<br />
<br />
When we start of with any programming language, it is necessary to know all <b> datatypes and character set </b> it supports<br />
For javascript I followed <a href="http://oreilly.com/javascript/excerpts/learning-javascript/javascript-datatypes-variables.html"> this post </a> on Oreilly.com <br />
<br />
<b> Is javascript pass by value or reference? </b> Check out my <a href="http://itsallabtamil.blogspot.in/2012/03/javascript-pass-by-reference-or-value.html"> blog post ;) </a><br />
<br />
Javascript is one of the languages ( might be only too ;) ) where point of declaration of a function matters in execution order<br />
You can understand the reason for above fact in this <a href="http://studiokoi.com/blog/article/execution_order_of_functions_and_variables_in_javascript_and_actionscript"> nice blog </a><br />
<br />
Understand <b> lexical scoping </b> before writing nested functions in javascript. <a href="http://blogs.msdn.com/b/kartikb/archive/2009/01/15/lexical-scoping.aspx">This article</a> might be helpful<br />
<br />
To have a in-depth knowledge in the concept of <b> closures and prototype chaining </b>, once you are aware of lexical scoping follow <a href="http://jibbering.com/faq/faq_notes/closures.html"> an awesome post </a><br />
Also beware of <a href="http://ayende.com/blog/3042/javascript-lexical-scopes-and-what-your-momma-thought-you-about-variables"> this anti pattern </a> while using closures<br />
<br />
Really nice blog on when and when not use <a href="http://www.yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/"> <b> new operator </b> [Don't dare to miss the comments on the post @yuiblog] </a><br />
<br />
Then go ahead with what we call <a href="http://joost.zeekat.nl/constructors-considered-mildly-confusing.html"> constructors in javascript </a><br />
<br />
Once you understand the concept of constructors and functions, you can go ahead with a bunch of <a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/"> design patterns </a> neatly explained<br />
<br />
Want to test yourself on the above said concepts??<br />
Try <a href="http://ejohn.org/apps/learn/"> this awesome piece </a> <br />
<br />
Other interesting concepts like<br />
<ul><li><a href="http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting"> Javascript Variable Hoisting </a></li>
<li><a href="http://kangax.github.com/nfe/"> Named function expressions </a></li>
<li><a href="http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/"> Javascript typeof </a></li>
<li><a href="http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/"> Javascript comma operator </a></li>
<li><a href="http://ejohn.org/blog/ecmascript-5-objects-and-properties/"> ECMAScript 5 </a></li>
<li><a href="http://www.reddit.com/r/javascript/comments/pm39d/hey_rjavascript_what_are_some_libraries_that/"> Awesome Javascript Libraries </a></li>
<li><a href="http://javascipt.info/"> Nice Javascript Tutorial specifically for setTimeout, setInteval, Memory Leaks, this </a></li>
<li><a href="http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/"> What is this for..in </a></li>
<li><a href="https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions"> Javascript Regular Expressions </a></li>
<li><a href="http://ejohn.org/blog/partial-functions-in-javascript/"> Javascript Partial Application </a></li>
<li>Try this <a href=""> Test </a> and Find the reason if you couldn't understand why is it so<a href="http://www.nczonline.net/blog/2010/01/26/answering-baranovskiys-javascript-quiz/"> here </a></li>
<li><a href="http://blogorama.nerdworks.in/"> One other good resource </a></li>
<li><a href="http://docstore.mik.ua/orelly/webprog/jscript/ch11_03.htm"> A touch and go on Javascript GC </a></li>
</ul><br />
One other blog post on <a href="http://accidentaltechnologist.com/javascript/7-resources-every-javascript-developer-should-know/"> javascript resources </a> online<br />
<br />
In the whole blog I never concentrated on Javascript's interaction with DOM. It is a very vaaaast play ground :)<br />
<br />
Hope all these links makes some sense to you :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-65507724201207584832012-04-18T19:37:00.000+05:302012-04-22T21:52:58.704+05:30Ubuntu 11.10 Bluetooth Issue & Exploration<br />
<b>Command Line Bluetooth Transfer</b><br />
This blog talks about the way to mount bluetooth enabled mobile phone for file transfer via <b> obexfs </b> <br />
and also a very nice way to transfer files without a GUI using <b> sdptool & ussp-push </b><br />
<br />
Don't forget the power of <b> sudo </b> whenever you get any permission denied error ;)<br />
<br />
Since I had upgraded my ubuntu version from 11.04 to 11.10. <br />
I never succeeded in sending files via bluetooth to my mobile phone.<br />
And finally the day has come, <br />
I Googled for the error that I use to get while trying to send files via bluetooth<br />
<b>"Permission Denied (13)"</b> and landed <a href='http://askubuntu.com/questions/67026/bluetooth-permission-denied-13-error'> Here </a><br />
From there I got redirected to <a href='https://bugs.launchpad.net/ubuntu/+source/gnome-bluetooth/+bug/872044'>Launch pad</a> where I found many people reporting the same issue.<br />
I got a chance to know some decent amount of distinct phone models too ;)<br />
And I got him & <a href='http://ubuntu-answers.blogspot.in/2011/11/bluetooth-on-ubuntu-1110.html'> HEEEE was the Guy </a> whom I was looking for.<br />
<br />
<i> Also The issue with 11.10 can be resolved by upgrading your blueman service too via ppa </i><br />
<br />
I just tried his way<br />
<pre class='brush:bash; highlight:[1,2,5]'>$ sudo apt-get install obexfs
$ hcitool scan
Scanning ...
3C:8B:FE:F6:1B:3A Tamilmani
$ obexfs -b 3C:8B:FE:F6:1B:3A /media/tamil
#Once I completed my transfer I unmounted it via
$ fusermount -u /media/tamil
</pre>It worked like a charm :) my phone got mounted & I'm able to transfer data<br />
<pre class='brush:plain'>From man pages
fusermount : mount/unmount fuse filesystem [-u==unmount in the above example]
obexfs : mount obexFTP(Object Exchange FTP) capable devices
obexfs -b[bluetooth]
</pre>Learn about <a href='http://en.wikipedia.org/wiki/Filesystem_in_Userspace'> FUSE Here </a><br />
From now my exploration started..<br />
<b>What is this hcitool do?</b><br />
From <b> man pages </b>: Configure Bluetooth Connections & send some special Commands to bluetooth devices<br />
Some Interesting Commands that we can send via hcitool:<br />
<pre class='brush:plain'>scan: Scans all available and visible bluetooth devices
dev : Display local device [the host where you run hcitool from]
name [addr] : Displays the name of the specified device[addr]
info [addr] : Print device name, version and supported features
and many more
[addr refers to BADDR of device -> unique radio frequency identifier, ex: 3C:8B:FE:F6:1B:3A]
</pre><br />
What <a href='https://wiki.archlinux.org/index.php/Bluetooth'> more </a>?<br />
I learn't how to transfer data without a gui :P<br />
<pre class='brush:bash; highlight:[1,9,14,15]'>$ sdptool browse 3C:8B:FE:F6:1B:3A
Service Name: Object Exchange
Service RecHandle: 0x10005
Service Class ID List:
"OBEX Object Push" (0x1105)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 5
"OBEX" (0x0008)
Profile Descriptor List:
"OBEX Object Push" (0x1105)
Version: 0x0100
$ sudo apt-get install ussp-push
$ ussp-push 3C:8B:FE:F6:1B:3A@5 /home/tamil/image.jpg image.jpg
</pre>A Brief explanation of the above<br />
<pre class='brush:plain'>sdp -> Service Discovery Protocol
sdptool -> Tool to send sdp queries to bluetooth devices
Available commands:
search : search for a service
browse : browse all available services
add : add a service to sdpd
and many more
</pre>So, using sdptool I figured out a list of services available in my destination bluetooth device<br />
Out of all the services, I found the channel [5 -> highlighted in the output] of OBEX Object Push service<br />
then using <br />
<b>ussp-push</b> -> program that can be used to send files using OBEX (OBject EXchange) protocol over Bluetooth<br />
I did transfer my file from my machine to my phone<br />
<pre class='brush:bash'>$ ussp-push [addr]@channel src dst #dst is just a filename not a path
</pre>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com1tag:blogger.com,1999:blog-4836497234580815703.post-86442946818603858222012-04-13T19:59:00.001+05:302012-04-13T20:01:09.728+05:30Interesting Javascript Facts Wishes to the web development world :) <br />
In the past 2 to 3 months I had chance to know about loads & loads of innovative <a href='http://www.reddit.com/r/javascript/comments/pm39d/hey_rjavascript_what_are_some_libraries_that/'> JS Libraries </a><br />
All of them made me wonder "Is there a thing that we can't do in JS?"<br />
I wish to share some facts which got me mad in to this language & very beginnerish ;)<br />
<br />
<b>What is {} + []?</b><br />
As soon as I saw this question my reply was "[object Object]"<br />
But the real answer was 0 :O<br />
Couldn't get any good guess on this, so posted <a href=' http://stackoverflow.com/questions/9021109/what-is-in-javascript'> @stackoverflow </a><br />
And I myself couldn't believe I missed it :P<br />
{} => Empty Block Scope & +[] => 0<br />
So, cometh thy answer :)<br />
Some more of the same kind <br />
{} + {} = NaN<br />
[] + [] = ""<br />
[] + {} = "[object Object]"<br />
<br />
<b>Why obj === +obj?</b><br />
I found this @ the source of <a href='http://backbonejs.org/'>Backbone.js</a><br />
I was wondering why should they check JS <b>number</b> type in such a way?<br />
Once again I got back to <a href='http://stackoverflow.com/questions/9188998/obj-length-obj-length-in-javascript'> Stackoverflow </a><br />
The reply once again stunned me up :D<br />
It was to save the network bandwidth of end user :)<br />
<b>After compressing the code:</b><br />
typeof(obj)=='number' [24 bytes]<br />
obj===+obj [13 bytes]<br />
<b>So, 11 Bytes saved :D</b><br />
<br />
<b>So why is this $.each("Boolean Number String Function Array Date RegExp Object".split(" "), function () {})</b><br />
This one is from jQuery :)<br />
The moment I saw this as a javascript kid <br />
Why not ["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object"] this???<br />
But this time I didn't seek Stackoverflow's help :P<br />
<b>After Compressing the code:</b><br />
["Boolean","Number","String","Function","Array","Date","RegExp","Object"] (74 Bytes)<br />
"Boolean Number String Function Array Date RegExp Object".split(" ") (69 Bytes)<br />
<b>So we saved 5 Bytes :)</b><br />
<br />
<b>And Finally one Crockford fact:</b><br />
The guy who renamed logical && and || meaningfully :P<br />
Because both the logical operators doesn't knock you back with the boolean result of the evaluation<br />
Instead<br />
<u>&& => Guard Operator </u><br />
<b>Reason:</b><br />
Statement: expr1 && expr2 <br />
Return Val: expr1 if expr1 evaluates to false else expr2<br />
Ex: <br />
<pre class='brush:javascript'> var a = 1 && 10, b, c = b && a ;
console.log(a); // Will be 10 rather true
console.log(c); // Will be undefined rather false
</pre> <u>|| => Default Operator</u><br />
<b>Reason:</b><br />
Statement: expr1 || expr2<br />
Return val: expr1 if expr1 evaluates to true else expr2<br />
Ex:<br />
<pre class='brush:javascript'> var a = 10 || 1, b, c = b || a ;
console.log(a); // Will be 10 rather true
console.log(c); // Will be 10 rather true
</pre><br />
Default Operator is most widely used to handle browser level inconsistencies like<br />
<pre class='brush:javascript'>evt = event || window.event;
src = evt.target || evt.srcElement;
</pre><br />
Also the Guard Operator<br />
<pre class='brush:javascript'>body = document && document.body; //If document exists return document body
complexBody = document && (document.body || document.getElementsByTagName(body)[0]) //Using both guard and default
</pre><br />
Enjoy Javascript :) It has the most crazy useful parts than anyother language does :DTamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-91924324419852354892012-03-14T18:10:00.000+05:302012-05-11T00:22:23.595+05:30Cassandra PHPCassa & Composite TypesThis post is updated inorder to support phpcassa 1.0.a.1<br />
<br />
<h3>Cassandra Composite Type using <a href='https://github.com/thobbs/phpcassa'>PHPCassa</a></h3><br />
<b>phpcassa 1.0.a.1 uses namespaces in PHP which is supported in PHP 5 >= 5.3.0</b><br />
Make sure you have the relavant package. <br />
The script mentioned below is the copy of <a href="https://github.com/thobbs/phpcassa/blob/master/examples/composites.php"> PHPCassa Composite Example </a><br />
<br />
I will explain it step by step<br />
<br />
<b> (1) Creating Keyspace using PHPCassa</b><br />
Name => "Keyspace1"<br />
Replication Factor => 1<br />
Placement Strategy => Simple Strategy<br />
<b> (2) Creating Column Family with Composite Keys using PHPCassa </b><br />
Name => "Composites"<br />
Column Comparator => CompositeType of LongType, AsciiType (Ex: 1:example)<br />
Row Key Validation => CompositeType of AsciiType, LongType (Ex: example:1)<br />
Sample Row:<br />
'example':1 => { 1:'columnName': "value", 1:'d' => "Hai", 2:'b' => "Fine", 112:'a' => "Sorry" } <br />
Columns are sorted Based on Component types as shown above<br />
112 > 2 as LongType but "112" < "2" as Ascii
Cassandra Properly honors the type mentioned on column family definition
I have used <b> '' </b> to denote ascii. Ignore them as values<br />
<pre class="brush:php">require_once(__DIR__.'/../lib/autoload.php');
use phpcassa\Connection\ConnectionPool;
use phpcassa\ColumnFamily;
use phpcassa\ColumnSlice;
use phpcassa\SystemManager;
use phpcassa\Schema\StrategyClass;
// Create a new keyspace and column family
$sys = new SystemManager('127.0.0.1');
$sys->create_keyspace('Keyspace1', array( // (1)
"strategy_class" => StrategyClass::SIMPLE_STRATEGY,
"strategy_options" => array('replication_factor' => '1')
));
// Use composites for column names and row keys
$sys->create_column_family('Keyspace1', 'Composites', array( //(2)
"comparator_type" => "CompositeType(LongType, AsciiType)",
"key_validation_class" => "CompositeType(AsciiType, LongType)"
));
</pre><br />
<br />
<b> Start a connection pool, create an instance of Composites ColumnFamily </b><br />
<pre class="brush:php">$pool = new ConnectionPool('Keyspace1', array('127.0.0.1'));
$cf = new ColumnFamily($pool, 'Composites');
</pre><b> Specifying Row Keys and Column Keys </b><br />
Both our row key [<i>key_validation_class</i>] and column key [<i>comparator</i>] are composite types. <br />
That means our key has components in them and types of each component might differ<br />
So, we can't specify the keys as a single entity. They might violate the data types that cassandra cluster expects<br />
<b>For ex: </b> in our case of row keys: Component 1 is Ascii & Component 2 is Long<br />
When a write or read request is sent to cassandra, the type property should be properly maintained<br />
Specifying "key:1" won't work and would result in an cassandra exception<br />
<br />
Hence we maintain components of key as a php array and specify <b>insert_format & return_format </b> as an array.<br />
Ex: $key1 = array("key", 1); //Ascii, Long<br />
Other available formats for insert and return are<br />
<ul><li>DICTIONARY // Here, array keys correspond to row keys. So, we can't use this as our keys have components</li>
<li>OBJECT // This is almost same that thrift returns</li>
</ul>Whereas for columns, each column corresponds to a value. Hence it will be <b> array ( array ( components ) , value ) </b><br />
Here the array inside an array is required because php associative arrays don't support anything other than string keys.<br />
As we need to preserve type. We can't specify "columnKey"=>value anymore. <br />
Hence we map them in to an array as <i> array(key, value) where key itself is an array(components) </i><br />
<pre class="brush:php">// Make it easier to work with non-scalar types
$cf->insert_format = ColumnFamily::ARRAY_FORMAT;
$cf->return_format = ColumnFamily::ARRAY_FORMAT;
// Composite Row Keys ()
$key1 = array("key", 1);
$key2 = array("key", 2);
$columns = array(
array(array(0, "a"), "val0a"),
array(array(1, "a"), "val1a"),
array(array(1, "b"), "val1b"),
array(array(1, "c"), "val1c"),
array(array(2, "a"), "val2a"),
array(array(3, "a"), "val3a")
);
$cf->insert($key1, $columns);
$cf->insert($key2, $columns);
</pre><br />
Then we fetch data<br />
<b> (1) Get all the columns corresponding to a key </b><br />
<b> (2) insert and return format is array so accessing via index </b><br />
<b> (3) Should output an array of components of column name </b><br />
<pre class="brush:php">//Constructor of Column Slice
__construct( mixed $start = "", mixed $finish = "", integer $count = phpcassa\ColumnSlice::DEFAULT_COLUMN_COUNT, boolean $reversed = False )
</pre><b> (4) ColumnSlice </b> => <i> ColumnSlice(array(1), array(1)) </i><br />
<ol><li>$start => array, means composite type<br />
Ex: array(component, array(component, INCLUSIVE_FLAG), ...) // inner array is component specific and required only if you wish to override INCLUSIVE_FLAG</li>
<li>$end => Same as $first </li>
</ol>So, we ask for all columns whose first component [note the array, coz of composite type] is with value 1 to 1. <br />
And that Indirectly means, all columns with first component 1<br />
<b>(5) $start=> "" </b> means beginning of the row and <br />
array(1, array("c", false)) means, everything less than 1:c as per sorting I mentioned in the beginning<br />
<b> (6) </b> Shortlists all values based on the first component <i> exclusive of 0 and 2 </i><br />
<b> (7) </b> Shortlists all values based on the first component <i> exclusive of 0 and 2 in reverse </i> (Notice $reversed set to true)<br />
<pre class="brush:php">// Fetch a user record
$row = $cf->get($key1); //(1)
$col1 = $row[0];
list($name, $value) = $col1; //(2)
echo "Column name: ";
print_r($name); //(3)
echo "Column value: ";
print_r($value);
echo "\n\n";
// Fetch columns with a first component of 1
$slice = new ColumnSlice(array(1), array(1)); // (4)
$columns = $cf->get($key1, $slice);
foreach($columns as $column) {
list($name, $value) = $column;
var_dump($name);
echo "$value, ";
}
echo "\n\n";
// Fetch everything before (1, c), exclusive
$inclusive = False;
$slice = new ColumnSlice('', array(1, array("c", $inclusive))); // (5)
$columns = $cf->get($key1, $slice);
foreach($columns as $column) {
list($name, $value) = $column;
echo "$value, ";
}
echo "\n\n";
// Fetch everything between 0 and 2, exclusive on both ends
$slice = new ColumnSlice( // (6)
$start = array(array(0, False)),
$end = array(array(2, False))
);
$columns = $cf->get($key1, $slice);
foreach($columns as $column) {
list($name, $value) = $column;
echo "$value, ";
}
echo "\n\n";
// Do the same thing in reverse
$slice = new ColumnSlice( //(7)
$start = array(array(2, False)),
$end = array(array(0, False)),
$count = 10,
$reversed = True
);
$columns = $cf->get($key1, $slice);
foreach($columns as $column) {
list($name, $value) = $column;
echo "$value, ";
}
echo "\n\n";
// Clear out the column family
$cf->truncate();
// Destroy our schema
$sys->drop_keyspace("Keyspace1");
// Close our connections
$pool->close();
$sys->close();
</pre>Actually this version of PHPCassa is an awesome revamp from its later version.<br />
<ul><li>This has come out with Thrift 0.8 Support</li>
<li>Composite Type Support [no more serialize or unserialize required ;)]</li>
<li>Full Support for Batch Mutate</li>
<li>Implementation using namespaces</li>
<li>All new <a href="http://thobbs.github.com/phpcassa/api/"> API Reference</a> </li>
<li>And Complete <a href="https://github.com/thobbs/phpcassa/tree/master/examples"> Examples </a> </li>
</ul>Awesome work by Tyler Hobbs :)<br />
Hope this helps :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com12tag:blogger.com,1999:blog-4836497234580815703.post-70075968288404240212012-03-14T16:02:00.002+05:302012-03-17T16:00:01.098+05:30Javascript ASI and join vs concat(+)<h3><b> Javascript Automatic Semicolon Insertion </b> </h3><br />
I came across a nice implication of Automatic Semicolon Insertion while developing an API in javascript.<br />
<br />
I'll let you guess at first as usual. Try the following<br />
<pre class='brush:javascript'>function asi() {
var a = 10,
b = 20
c = 30;
this.log = function () {
console.log(a,b,c);
};
this.set = function (A,B,C) {
a=A;
b=B;
c=C;
}
}
var a = new asi();
a.log();
var b = new asi();
b.log();
a.set(11,21,31);
b.log();
b.set('This', 'is', 'wrong');
a.log();
</pre><br />
<pre class='brush:javascript'>//Expected output
10 20 30
10 20 30
10 20 30
11 21 31
//What happened??
10 20 30
10 20 30
10 20 31
11 21 wrong
</pre><br />
<b> How Come? </b><br />
<b> First Thing to note: </b><br />
See Closely at line 3 there is a comma operator missing. So, now parser will decide what to do :P<br />
<u>Remember: </u><br />
Whenever a statement misses a semicolon and if the statement following it makes sense along with the former. <br />
Then JS engine will not place a semicolon. Perhaps it parse them as a single statement. [Refer <a href='http://itsallabtamil.blogspot.in/2011/11/js-automatic-semicolon-insertion.html' > My Prev Post </a>]<br />
<u>Implication:</u><br />
var a=10,b=20 remains a incomplete statement without a semicolon <br />
var a=10,b=20c=30; doesn't makeout a valid javascript statement. So ASI makes it var a=10,b=20;c=30; [converse of the above]<br />
<b> Finally: </b><br />
The variable c is assigned before declaration in the scope of function ASI<br />
<u>Remember:</u><br />
If a variable is used before declaring it in function scope &&<br />
If the variable is not declared anywhere in the scope chain of the function<br />
Then it will become a property of the Global Scope or the window<br />
<u>Implication:</u><br />
Hence, variable 'c' is assumed to be declared in the global scope rather in function ASI()<br />
<br />
That is all to say about it :) <br />
Better don't save semicolons :P <br />
Use them whenever is needed. <br />
So, that you will be able to trace back errors nicely in case of unintentional errors like the above.<br />
<br />
<h3><b> Next is about Join Vs Concat(+) </b></h3><br />
I was going through many of the test regarding this context <a href='http://jsperf.com/search?q=join'> @jsperf </a> <br />
I inferred that in all modern browsers (+) for concatenation is optimized in a really nice way [in some cases (+) was 100 times better than join]. <br />
<br />
But I think the better criteria to choose one among them should be the usecase.<br />
Because both of them will be able to do job in less than a ms<br />
<br />
Following is an example why do I feel join is safer than (+)<br />
<pre class='brush:javascript'>function whyJoin() {
var a, b, c, delim = '&';
return {
setter: function (A, B, C) {
a = A;
b = B;
c = C;
},
concatMe: function () {
return a+delim+b+delim+c;
},
joinMe: function () {
return [a, b, c].join(delim);
}
};
}
var test = whyJoin();
test.setter('This', 'is', 'Good');
var c = test.concatMe();
var j = test.joinMe();
console.log(c.split('&'));
console.log(j.split('&'));
test.setter('This', 'is');
c = test.concatMe();
console.log("Doesnt look good", c);
j = test.joinMe();
console.log("Seems Fine", j);
console.log(c.split('&'));
console.log(j.split('&'));
test.setter('This', 'is', null);
c = test.concatMe();
console.log("Doesnt look good", c);
j = test.joinMe();
console.log("Seems Fine", j);
console.log(c.split('&'));
console.log(j.split('&'));
</pre>If you had noticed your console following will be the output<br />
<pre class='brush:javascript'>["This", "is", "Good"]
["This", "is", "Good"]
Doesnt look good This&is&undefined
Seems Fine This&is&
["This", "is", "undefined"]
["This", "is", ""]
Doesnt look good This&is&null
Seems Fine This&is&
["This", "is", "null"]
["This", "is", ""]
</pre><br />
Hope you noticed, In Concat(+) undefined or null is converted to their string equivalent and appended which might be undesired in some cases.<br />
<br />
Also join keeps things clear & clean. <br />
For ex: If delimiter is going to be the same across all concatenation or operands already exists as an array.<br />
<br />
Concat(+) is really useful in many cases<br />
For ex: If the concatenation is not based on some delimiters & number of concatenation operations is less<br />
<pre class='brush:javascript'>var result = '<li>'+param+'</li>';
</pre>In some cases I feel using both keep things clear. <br />
For ex:<br />
<pre class='brush:javascript'>for(some condns) {
result += [param, param, param].join('&');
}
</pre><br />
But Google Optimization suggests creating a string builder for the above case.<br />
<pre class='brush:javascript'>function stringBuilder() {
this.needls = [];
}
stringBuilder.prototype.push = function (needle) {
this.needls.push(needle);
};
stringBuilder.prototype.build = function () {
var result = this.needls.join('');
this.needls = [];
return result;
};
var strBuilderInstance = new stringBuilder();
for(some cdns) {
strBuilderInstance.push([param, param, param].join('&'));
}
var result = strBuilderInstance.build();
</pre><br />
All the tests performed in jsperf are performance test :) <br />
Better decide things based on your usecase because javascript is fast enough but the DOM is taking all the time :) -> Douglas CrockfordTamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com2tag:blogger.com,1999:blog-4836497234580815703.post-75529752013221101322012-03-13T14:20:00.001+05:302012-03-13T15:39:23.443+05:30Is Javascript Pass By Reference or Pass By Value?Javascript - Pass By Reference or Value?<br />
<b>Javascript Types:</b> <br />
string, number, boolean, null, undefined are javascript primitive types. <br />
functions, objects, arrays are javascript reference types.<br />
<br />
<b>Difference?</b><br />
One of them is pass by reference and value.<br />
<br />
I'm Considering string from primitive type and object from reference type for explanation.<br />
<br />
Try guessing the alerts in the following examples yourself before reaching the answers<br />
<br />
<pre class="brush:javascript">//Example 1
function test(student) {
student = 'XYZ';
alert(student);
}
var a = 'ABC';
test(a);
alert(a);
//Example 2
function test(student) {
alert(student.name);
student.marks = 10;
student.name = 'XYZ';
}
var a = {name:'ABC'};
test(a);
alert(a.name);
//Example 3
function test() {
var student;
return {
setter: function (a) {
student = a;
},
getter: function () {
return student;
},
change: function () {
student.name = 'XYZ';
}
}
}
var a = {name:'ABC'};
var b = test();
b.setter(a);
a.name = 'DEF';
alert(b.getter().name);
b.change();
alert(a.name);
//Example 4
function test() {
var student;
return {
setter: function (a) {
student = a;
},
getter: function () {
return student;
},
change: function () {
student.name = 'XYZ';
}
}
}
var a = {name:'ABC'};
var b = test();
b.setter(a);
a = {name:'DEF'};
alert(b.getter().name);
b.change();
alert(a.name);
</pre><br />
Try reasoning why are they so if you are wrong, before reaching the explanation<br />
<br />
<pre class='brush:javascript'>//Example 1
alert 1: XYZ
alert 2: ABC
//Example 2
alert 1: ABC
alert 2: XYZ
//Example 3
alert 1: DEF
alert 2: XYZ
//Example 4
alert 1: ABC
alert 2: DEF
</pre><br />
<b>Reason</b><br />
<br />
<b>Example 1:</b><br />
string is a primitive type & variables hold the values for primitive types. <br />
Primitives are passed by value in javascript.<br />
So, change in 'student' will never affect 'a' and vice versa<br />
<br />
<b>Example 2:</b><br />
object is a reference type & variables hold the reference rather value for reference types<br />
Reference types are passed by reference in javascript<br />
Both a & student refer to the same object. Hence change in 'student' reflects over 'a'.<br />
**Remember reference of 'student' never points to 'a', it follows the reference chain of 'a' and starts referring to the core object.<br />
<br />
<b>Example 3:</b><br />
Reason same as Example 2<br />
Created this example to show that change made in 'a' too reflects back in 'student'<br />
<br />
<b>Example 4:</b><br />
This example tests your real understanding.<br />
If you can reason this out now, then you can grade your self good in this topic<br />
<br />
Although a's reference has changed to new object, it didn't affect student's reference.<br />
Reason: point to remember mentioned in Example 2. <br />
You have to understand this clearly :)<br />
<br />
Hope I had done some justice. The same can be proved for other primitive and reference types :)<br />
<br />
You actually don't need function calls to prove these concepts.<br />
<br />
<pre class='brush:javascript'>//Equivalent to Example 1
var a = 10;
var b = a;
a = 20;
console.log(a, b);
//Equivalent to Example 2 & 3
var a = {value:1};
var b = a;
a.name = 'xyz';
b.value = 10;
console.log(a, b, a===b);
//Equivalent to Example 4
var a = [1,2,3];
var b = a;
b[0] = 10;
console.log(a, b, a===b);
a = [5,6,7];
console.log(a, b, a===b);
</pre><br />
But I used to function to explain the effects over 'passing' rather 'assignment|copying' :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com2tag:blogger.com,1999:blog-4836497234580815703.post-73265012871482972462012-01-31T21:36:00.002+05:302012-03-14T22:12:21.163+05:30CAPTCHA - A Revolution<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<b>CAPTCHA</b> = Completely Automated Public Turing test to tell Computers and Humans Apart<br />
<br />
<b>What is a CAPTCHA?</b><br />
A System built by Luis von Ahn, Manuel Blum, Nicholas J. Hopper, and John Langford of CMU to make sure that user who is active at the other end is a Human and not a bot. This was initially done to prevent bots entering yahoo chat rooms and redirecting the users to someother sites.<br />
<br />
CAPTCHA - <b>Reverse Turing Test</b>:<br />
Yups, CAPTCHA is a reverse turing test because it reverses the role of computers and human. Computer is a device designed to perform what human want it to. But in the case of CAPTCHA it is reversed. It is completely automated, so computer challenges you to perform some action to identify that you are a human.<br />
<br />
Initially [even now] CAPTCHA was an distorted image with some characters in it which would make lives of bots harder to detect them but which wouldn't affect human though<br />
<br />
Next generation of CAPTCHA carried a audio link with the distorted image beside to help visually challenged people<br />
<br />
Although CAPTCHA are automatically generated they are easily breakable using some techniques like OCR(Optical Character Recognition) or by understanding the underlying logic of automation.<br />
<br />
And Now, people started their own implementation including<br />
<br />
<b>Mathemetical Captcha</b> => What is 1 + 1?<br />
<b>Image/Visual Captcha</b> => Who is alice in the photo tagged with friends? [FB uses it to detect legitimate user of an account]<br />
and so on<br />
<br />
But the real master piece is reCaptcha [Powered by Google]<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-SCSIh9acLjs/TygfxFKh1uI/AAAAAAAAAG4/KenQf2kxIFo/s1600/image.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-SCSIh9acLjs/TygfxFKh1uI/AAAAAAAAAG4/KenQf2kxIFo/s1600/image.jpg" /></a></div>
<br />
<b><br /></b><br />
<b><br /></b><br />
<b><br /></b><br />
<b>What is great in that?</b><br />
It is great because it knows the value of human time. A test that unites human power :)<br />
<b>How?</b><br />
If you had noticed any recaptcha there will be two space separated words<br />
Consider the image shown for example [said allectst]<br />
<b>Where does this words come from?</b><br />
These words come from the process of digitizing old text with <a href="http://en.wikipedia.org/wiki/Optical_character_recognition">OCR</a><br />
<b>Means?</b><br />
Inorder to generate digital version [ex: pdf] of a book which was written way back digitized books or word processing tools came in to existence, people use a technology which scans the book and takes a photocopy[image] of it. Then it tries to recognize the characters using image processing technique called OCR and digitizes the old text.<br />
<b>What it has to do with reCaptcha?</b><br />
OCR is an automated tool to recognize characters from an image. It is not guaranteed that it will be able to recognize all characters with out any discrepancies. For ex. T can be interpreted as I based on some fonts or clarity of the image.<br />
<br />
So, what recaptcha people do is<br />
Pick two words; one was successfully recognized by ocr, <b>said</b> and the other it wasn't able to, <b>allecstst. </b><br />
Challenge the user for CAPTCHA test.<br />
If the user answers the one successfully recognized by ocr [<b>said</b>] correctly, it will confirm that the user is a human. And the other word is kind of a poll. The same unrecognized word will be shown to a group of people [say 10].<br />
If out of 10, 7 [i.e., majority] were able to recognize <b>allecstst</b> as <b>allecstst</b> and the rest understood it as <b>alleestst,</b> then the unrecognized word is considered as <b>allecstst</b> as majority falls for it. Hence a word is digitized in a book :)<br />
<br />
So, without your knowledge you are helping digitize a book whenever you fill a recaptcha :) Be happy whenever you answer a recaptcha and proud to be united :)<br />
A book is being digitized whenever a user signs in to Facebook, gmail, linked in, etc.,<br />
<br />
From the site<br />
<b>About 200 million CAPTCHAs are solved by humans around the world every day. In each case, roughly ten seconds of human time are being spent. Individually, that's not a lot of time, but in aggregate these little puzzles consume more than 150,000 hours of work each day. What if we could make positive use of this human effort? reCAPTCHA does exactly that by channeling the effort spent solving CAPTCHAs online into "reading" books.</b><br />
<br />
visit <a href="http://www.google.com/recaptcha/learnmore">this</a> site to learn more and feel great :)<br />
<br /></div>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com1tag:blogger.com,1999:blog-4836497234580815703.post-27413979665238804572012-01-09T21:12:00.000+05:302012-09-07T08:11:36.893+05:30Nodejs Modules and Export Explained<div dir="ltr" style="text-align: left;" trbidi="on"><br />
Enjoyed a week playing around with nodejs :) Lets share<br />
<br />
Simple Node Server [http://localhost:6666]:<br />
<br />
<pre class="brush:javascript">var http = require('http');
var server = http.createServer(function (req, res) {
// Do Whatever you want
res.writeHead(200, {'Content-Type':'text/plain'});
res.end('Running');
}).listen(6666, function () {
console.log('Node Runs on port 6666');
});</pre><br />
<b>How to install a node_module?</b><br />
NPM is a powerful package manager for node which you can use to install node modules<br />
Ex:<br />
npm install redis<br />
<br />
The above command installs redis module in <b>./node_modules/redis</b> directory<br />
<br />
<b>How to use a module?</b><br />
Use require() method<br />
<br />
Ex:<br />
require('redis')<br />
<br />
<b>How will node resolve the modules?</b><br />
Consider<br />
<br />
<pre class="brush:javascript">/home/xxx/sample
|___ index.js
|___ node_modules
|____ redis
|____lib/
...
|____ my_module
|____node_modules
|____first.js
|____test.js
</pre><br />
<br />
<pre class="brush:javascript">//test.js
var redis = require('redis');
</pre><br />
So node will look for redis module in<br />
<br />
1.my_module/node_modules/<br />
2.sample/node_modules/<br />
3.xxx/node_modules/<br />
4.home/node_modules<br />
5./node_modules<br />
<br />
Also some <a href="http://nodejs.org/docs/latest/api/modules.html#loading_from_the_global_folders"> global folders </a><br />
<br />
You can exploit this behaviour nicely if planned :)<br />
<br />
<b>Will node load the module everytime I request it to via require?</b><br />
No, It won't load the module everytime you request<i> untill the module requested resolves to a location different from previously loaded location</i>.<br />
Ya, Node caches the module<br />
<br />
<b>Cache means?? What will get cached?</b><br />
uh uHHH... Lets get deeper into modules before this question<br />
<br />
<b>How to write your own module?</b><br />
Simple... Let us write a module which performs lowercase to uppercase conversion<br />
<br />
<pre class="brush:javascript">//simple.js
var stringtoUpper = function (text) {
return text.toUpperCase();
};
exports.toUpper = stringtoUpper;</pre><br />
Done :)<br />
<br />
<pre class="brush:javascript">//test.js
var utils = require('./simple');
console.log(utils.toUpper('this is text'));
//Execution
node test.js
>THIS IS TEXT
</pre><br />
<b>What is that exports?</b><br />
That is whatever you wish to expose to the src module that requires the destination module.<br />
This is <b>shared between all instances</b> of the current module.<br />
exports.toUpper same and equal to module.exports.toUpper,<a href='http://stackoverflow.com/questions/10495801/node-js-module-exports/10496831#10496831'> [exports === module.exports] </a> nice way to use.<b><i> module is the referrence to the current module</i></b> :)<br />
Also you can name your export different from it's actual name. As you can see in the above example. Actual function's name is stringtoUpper, but exports' name is toUpper<br />
<br />
Consider the same simple.js and instead <b><i>exports.toUpper = stringtoUpper</i></b> replace with<br />
<br />
1.module.exports.toUpper = stringtoUpper;<br />
2.module.exports = stringtoUpper;<br />
3.module.exports = new stringtoUpper('this is a text');<br />
<br />
All the three are different<br />
<br />
<b>module.exports is an object</b><br />
1 makes it {toUpper: [Function]]}<br />
2 makes it [Function] // We can use this a constructor function<br />
3 makes it an object of stringtoUpper class<br />
<br />
<b>After require('test.js'); to use the exports, follow</b><br />
1 : simple.toUpper('This is a text')<br />
2 : simple('this is a text') or require('simple')('this is a text') or new simple('this is a text');<br />
3 : You can access all public members. Here there is none<br />
<br />
<b>Methods 2 & 3 overrides the entire object</b>, means whatever might be there initialised before via exports will be overridden<br />
Ex:<br />
module.exports.a = 10;<br />
module.exports.b = 20;<br />
module.exports = 20; // will override a & b<br />
Hope you understand the reason. module.exports itself is an object and members of it can be initialised either as module.exports.a, module.exports.b but when module.exports = 20 happens the whole object is initialised with new value<br />
<br />
Now lets comeback to caching<br />
<br />
<b>node caches all these exports</b> of a module when they are loaded for the first time<br />
<br />
<b>1 & 2 has no effect</b> on caching since they are just functions they can be called n number of times with change in parameter<br />
<br />
But 3 is different. The<b> object returned is cached.</b> So how many ever time you load the module after first time, no instantiation take place [Kind of singleton]. Because you are exporting only one object of the class.<br />
<br />
So, If you are looking for stateful implementation across modules you can go for 3, else go for 1 or 2<br />
<br />
Happy Node :) Hope this helps :)</div>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com4tag:blogger.com,1999:blog-4836497234580815703.post-77330761419885946482011-12-27T22:36:00.000+05:302012-04-11T12:06:06.602+05:30HTML Input Place Holder<div dir="ltr" style="text-align: left;" trbidi="on">A Simple way to implement placeholder in a Input Field. Although HTML 5 by default provides placeholders[placeholder attribute], it falls short in Cross Browser Compatibility<br />
<br />
<b>Construct A Simple Form</b><br />
<br />
Username: <input type="text" /><br />
<br />
Let's Implement Placeholders Now [With jQuery]<br />
<br />
<b>Change the HTML To</b><br />
HTML:<br />
<pre class="brush:html"><div class="form-container"><input class="name-field" type="text" />
<span class="place-holder"> Username </span>
</div></pre><b>Result</b><br />
<div class="form-container"><input type="text" /> Username </div><br />
<b>Apply CSS and Overlay placeholder over Input Element</b><br />
CSS:<br />
<pre class="brush:css">.place-holder {
position:relative;
left:-245px;
color:#AAA;
z-index:1;
}
.name-field {
width:250px;
background:#FFF;
z-index:0;
}
</pre><b>Result</b><br />
<div class="form-container"><input class="name-field1" type="text" /><span class="place-holder1"> Username </span> <br />
</div><br />
<b>Handle Focus and Blur Event :)</b><br />
jQuery:<br />
<pre class="brush:javascript">$().ready(function () {
function hideHolder() {
$('.place-holder').hide();
}
function showHolder() {
if($('.name-field').val() == '') {
$('.place-holder').show()
}
}
$('.name-field').focus(hideHolder);
$('.name-field').blur(showHolder);
$('.place-holder').click(function () {
$('.name-field').trigger('focus');
});
});
</pre><style type="text/css">
.place-holder,.place-holder1 {
position:relative;
left:-245px;
color:#AAA;
z-index:1;
}
.name-field,.name-field1 {
width:250px;
background:#FFF;
z-index:0;
}
</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript">
</script><script type="text/javascript">
$().ready(function () {
function hideHolder() {
$('.place-holder').hide();
}
function showHolder() {
if($('.name-field').val() == '') {
$('.place-holder').show()
}
}
$('.name-field').focus(hideHolder);
$('.name-field').blur(showHolder);
$('.place-holder').click(function () {
$('.name-field').trigger('focus');
});
});
</script><br />
<b> Result </b><br />
<div class="form"><div class="test"><input class="name-field" type="text" /><span class="place-holder"> Username </span></div></div></div><br />
We are Done. Also You Can extend this upto 'N' number of Elements. You can also play with <b>z-index</b> value instead <b>show()&hide() jQuery functions</b> :)<br />
<br />
<b> Pros over playing around input's value attribute </b><br />
<ul><li>Styling for placeholder is decoupled from input element and vice versa</li>
<li>The value of input element will be '' always if it is left empty</li>
<li>Simple </li>
</ul><br />
<b> Cons </b><br />
Just leave a comment if there is any :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-55024059030292931942011-11-30T16:05:00.000+05:302012-03-14T16:08:41.950+05:30JS Automatic Semicolon Insertion<div dir="ltr" style="text-align: left;" trbidi="on">
Semicolon; Why should I care? <br /><blockquote style="border: 1px solid; padding-bottom: 13px; text-align: center;">
<br />"Javascript is the only language which people dare to use before learning"<br />- Crockford</blockquote>
<br />Actually I, myself belong to that category of people whom crockford mentions :)<br />But trying to be out..<br /><br /><b>So, What's new today? </b><br />Just a informative writeup about ASI<br /><br /><b>ASI?</b><br />Ya, Javascript Automatic Semicolon Insertion<br /><br /><b>What is a legal statement in Javascript?</b><br />Following are some<br /><pre class="brush:javascript">
var a=10;
a;
b++;
b+=1;
;;; // 3 Empty Statements
+a
var a = function() { };
{
a
b
c
};</pre>
<br />Lets start<br />Try the following<br /><pre class="brush:javascript">
var a=10;
function test() {
var b;
b = a;
b+=1
}
console.log(a)</pre>
<br />Even though I didn't insert any semicolon [Statement Terminator] in line 5 and 7, the JS engine never throws an syntax error.<br /><b>Reason:</b> ASI Construct<br /><br /><b>Rules to remember:</b><br /> ** ASI will insert one for you, if you specify a line terminator @ [no line terminator] mentioned <br /> in the grammar specification<br /> ** Whenever a statement misses a semicolon and if the statement following it makes sense along with the former. <br /> Then JS engine will not place a semicolon. Perhaps it parse them as a single statement<br /> ** If the statement is the last one inside a scope then you might consider missing semicolons. ASI will take care of<br /><br /><b>Where ASI will mislead?</b><br />There are 6 places<br />1 return<br />2 break<br />3 continue<br />4 Post ++<br />5 throw<br />6 Anywhere :P<br /><br />Let's see the grammar for the first five<br />1. Return Statement -> return [no line terminator] (space expression) <br />2. Break Statement -> break [no line terminator] (space label) <br />3. Continue Statement -> continue [no line terminator] (space label) <br />4. Post Increment Statement -> [operand] [no line terminator] ++ <br />5. Throw Statements -> throw [no line terminator] [space expression] <br /><br /><b>Try it yourselves:</b><br /><pre class="brush:javascript">
function test() { //Sample 1 Fails Silently
var a =10;
return
{
avalue: a
};
}
console.log(test().avalue);
function test() { //Sample 2 Throws Syntax Error
var a =10, b = 10;
return
{
avalue: a,
bvalue: b
};
}
console.log(test().avalue);</pre>
<br /><b>Transformation:</b><br /><pre class="brush:javascript">
function test() { //Sample 1 Fails Silently
var a =10;
return; --ASI rule 1-- Returns Undefined
{
avalue: a
};
}
console.log(test().avalue);
function test() { //Sample 2 Throws Syntax Error
var a =10, b = 10;
return; // --ASI rule 1-- Returns Undefined
{ //Considered as a Block Statement
avalue: a, //Considers avalue as label and 'a' as the statement under it
bvalue: b //Considers bvalue as label and 'b' as the statement under it
};
}</pre>
<br />According to ASI rule 1, there should not be any line terminator between return keyword and optional value. <br />If there is line terminator then JS parser inserts one ';' for you and makes your life difficult in case 2 and even more in case 1 [fails silently]<br /><br /><b>Try it yourselves:</b><br />These things likely won't happen but...<br /><pre class="brush:javascript">
outer:for(j=0;j<3;j++) //Sample 1
{
test:for(var i = 0;i < 3; i+=1) {
if(i === 2) {
break // JS Engine Inserts a ; and 'outer' becomes a reference to outer loop
outer;
}
console.log(j);
}
}
console.log(i);
var a = -10; //Sample 2
var b = 10
+a; // Rule 2
console.log(a+' '+b);
var a, b = 10, c = 10, d = 1, e = 3; //Sample 3
a = b + c
(d + e).toString(2); //Rule 2
var a = 10; //Sample 4
a
++;
var b = 1; //Sample 5
++
b;
var a = 10, b = 10; //Sample 6
if(true)
{
a++;
b++ // Rule 3
}</pre>
<br />Tidy programming always helps and will keep javascript good :)</div>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-31331014018136562752011-11-21T22:40:00.001+05:302011-11-22T12:59:40.061+05:30Making Javascript Good :)<div dir="ltr" style="text-align: left;" trbidi="on">
Somethings I learnt from Crockford :)<br /><b>Keep it right always :) </b><br /><pre class="brush:javascript">
function a() //Seems to be working but not :)
{
return
{
name: 'a'
};
}
console.log(a().name);
function a() { //Keep braces always right. It works :)
return {
name: 'a'
};
}
console.log(a().name);</pre>
<br />There is no concept of block level scoping in javascript but the syntax exists. So, the former falls in that block hole and returns undefined. <br /><br /><b>It's not c or c++</b><br /><pre class="brush:javascript">
var i = 'tamil';
for(var i = 0;i < 10;i++){
}
console.log(i);</pre>
<br />This is misleading because declaring 'var i' @ initialization of for-loop doesn't mean 'i' has the scope of the loop & it doesn't interfere with the one out. <br />There is no other scope than function scope in javascript. All our declarations are hoisted up to function scope no matter where ever they are. So, don't get misleaded :)<br /><br /><b>All you spend is 0 but you get a lot :)</b><br /><pre class="brush:javascript">
function sample() {
....do something
var j = 10;
....do something
}</pre>
<br />As I mentioned earlier there are no other scopes other than functions. So, what happens here is<br /><pre class="brush:javascript">
function sample() {
var j = undefined; // Hoisted to the top always. Better we do it meaningfully as var j = 10;
....do something
j = 10;
....do something
}</pre>
<br />Keep the declarations @ the beginning always. It costs you nothing but it might save your time in future :)<br /><br /><b>You might know what you are doing :)</b><br /><pre class="brush:javascript">
if(a = b) { //1
}
if(a == b) a(); c(); //2</pre>
<br />You might know what you are doing, but don't expect others<br />I might think for 1, It as either <br /><pre class="brush:javascript">
if(a == b) { //typo
}
//or
a = b;
if(a) {
}</pre>
<br />For 2<br /><pre class="brush:javascript">
if(a == b) {
a();
c();
}
//or
if(a == b) {
a();
}
c();</pre>
<br />Be clear for others too :) It helps<br /><br /><b>ALL is always bigger than LOT :) U gotta believe :P</b><br /><pre class="brush:javascript">
0 == false //true
'0'==false //true
'false'==false //false</pre>
<br />These might not affect in lots of places but lot !== all :P So, Always use<br /><pre class="brush:javascript">
0 === false //false
'0' === false //false
'false' === false //false</pre>
<br /><br /><b>Without with</b><br /><pre class="brush:javascript">
var test = { //1
name: 'xxx',
age: 12
}
var age = 100;
with(test) {
age = 200;
}
console.log(test.age);
console.log(age);
var test = { //2
name: 'xxx',
}
var age = 100;
with(test) {
age = 200;
}
console.log(test.age);
console.log(age);</pre>
<br />1 & 2 are not the same. So, don't rely on unreliable things out there :)<br /><br />I think I'm becoming Crockford's fan :)<br /></div>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-18522698643362140172011-11-17T16:20:00.001+05:302011-11-22T20:44:36.251+05:30A Javascript IntroductionHad a chance to read a nice javascript tutorial on variables and data types :)<br />
Let's share :)<br />
<br />
Q: How will I declare a variable? <br />
<pre class='brush:javascript'>var variablename;
</pre><br />
Q: I don't like variablename I wish to have $$$$$, Is it possible?<br />
A: Ya you can there is no restriction on varible names except <br />
1. It should start with either a alphabet or $ or _<br />
2. It should not use any reserve words like function, break, var, etc.,<br />
3. It should not use any of the operators [!@#%^&*()-+=]<br />
<br />
Q: Is there any javascript practise to declare variables?<br />
A: The answers is upto you. But most common practise is using CamelCase [Inherited from java]<br />
<pre class="brush:javascript"> var testvariable;
const TEST_CONSTANT;
function testFunction() {
}
testObject = new Object();
</pre>Another way is Hungarian Notation - appending type of the field/variable to its name<br />
<pre class="brush:javascript">var intAge = 19; //Interger
var strName = "xxxx"; //String
var bSet = false; //Boolean
var fpRate = 12.22; //Floating Point
var fMember = true; //Flag
</pre>Advantage:<br />
Following such conventions would increase the readability factor of the code.<br />
<br />
Q: What are the primitive types available?<br />
A: numeric, string, boolean are the 3 primitive types available in JavaScript.<br />
All these 3 Primitive types are wrapped by in-built Number, String and Boolean objects<br />
<br />
Q: Wrapped by - means?<br />
A: Number, String and Boolean are in-built objects, that support predefined methods for its instances.<br />
Applying such methods over primitive types will also work, though they are not an instance of any of the above mentioned in-built objects.<br />
<br />
Q: How is it possible?<br />
A: On applying those methods over primitive types an anonymous instance of respective in-buit object is created and destroyed once the process is completed<br />
Ex:<br />
<pre class='brush:javascript'>var age = 12;
var hexAge = age.toString(16);
</pre>Here, a Number object is created and it wraps primitive type of 'age', then toString is applied. Once the result is assigned, the instance created is destroyed<br />
<br />
Q: What about case sensitiveness?<br />
A: Javascript is Case Sensitive<br />
Ex:<br />
<pre class='brush:javascript'>var age = 12;
var Age = 22; //Valid and Different from age
</pre><br />
Q: What is this var? Why not int, float, String?<br />
A: Javascript supports loose typing. Type of the variable is defined based on its content<br />
Ex:<br />
<pre class='brush:javascript'>var age; //Type undefined
var intAge = 12; //Type numeric
var fpAge = 12.12; //Type numeric
var bAge = true; //Type boolean
var strAge = '12'; //Type string
var arMarks = new Array() //Type Array object
intAge = true; //Changes type to boolean
</pre>Note: <br />
Every Un Initialized variable either declared or not will be initialized with undefined;<br />
Every variable has a boolean value associated with it, to mention whether it is set or not<br />
<br />
Q: How does String work?<br />
A: Strings are array of characters quoted either using '' or "" [Either make no difference].<br />
Ex:<br />
<pre class='brush:javascript'>var strName = 'xxxx'; //valid
var strCity = "zz"; //valid
var strHobby = "I'm writing a blog"; //valid
var strMe = 'This is my number "12345"'; //valid
var strIV = 'I'm single'//Invalid
var strValid = 'I\'m single' //valid
</pre>Escaping characters is allowed and meaning is the same as other languages<br />
Ex: \n, \t, \\, \'<br />
<br />
Q: Guess the value of vars<br />
<pre class='brush:javascript'>var a = 1+2+3+'4';
var b = '4'+3+2+1;
</pre>A: a = 64 & b = 4321<br />
Reason:<br />
+ -> Means Concatenation over strings and Addition over numerics<br />
This is the only operator which converts numeric to string implicitly<br />
Others convert the other way round<br />
<br />
Q: Guess the value of vars<br />
<pre class='brush:javascript'>var a = 12/'4';
var b = '12'/'4';
var c = '12' > '4';
var d = '12' > 4;
</pre>A: a = 3 , b = 3 , c = false & d = true<br />
Reason for c:<br />
Both the operands are string so, it is equal to strcmp<br />
<br />
Q: Guess the value of vars<br />
<pre class='brush:javascript'>var test = new Array('1',{"sample":'2'},'3',4,5,1.2,3.4);
var a = test[0];
var b = test[1].sample;
var c = test[7];
var d = test['element'];
</pre>A: a = '1' ,b = 2 & c = undefined & d =undefined<br />
Reason:<br />
Array in javascript itself is an in-built object. It is just a heterogenous collection.<br />
It is always a hash where key for the hash is the index<br />
key---value <br />
'0'---1<br />
'1'---object<br />
'2'---'3'<br />
....<br />
So referencing an outof bound index [7] or not even an index ['element'] will never throw an error instead returns undefined <br />
<br />
<b>Some Typeconversion Facts</b><br />
Number<br />
Conversion: <br />
Explicit:<br />
Integer.parseInt()<br />
Integer.parseFloat()<br />
Implicit:<br />
Any arithmetic expression does implicit conversion [except + as mentioned earlier]<br />
<pre class='brush:javascript'>undefined----Nan
null---------Nan or 0 [Browser Dependent]
true---------1
false--------0
string-------corresponding value
object-------Nan
</pre>String<br />
Conversion:<br />
Explicit:<br />
toString<br />
Implicit:<br />
+ operator<br />
<pre class='brush:javascript'>undefined---'undefined'
null--------'null'
true--------'true'
false-------'false'
number------'value'
object------[ObjectType object]
</pre>Boolean<br />
<pre class='brush:javascript'>undefined---false
null--------false
number------false if value is 0 or NAN, true other wise
string------true if not empty [empty is not equal to null]
</pre><br />
What ever might be the type while outputting to the browser everything is converted to string :)<br />
<br />
If we use some undeclared variable a prototype chain is followed to figure out its value.<br />
Say <br />
<pre class='brush:javascript'>var test = {
'hai':'sample',
'testFunc':function sampleFunc(){}
};
alert(test.hai);
</pre>Chain:test->object [object is parent of all & end of prototype chain]<br />
<br />
Here object test has its own prototype. On executing test.hai JS engine checks for hai in test's prototype. If not defined, it follows the prototype chain of test which is followed by object. If it couldn't find it in it's prototype it returns undefined instead any error.<br />
<br />
You cannot access undefined of undefined, Means<br />
<pre class='brush:javascript'>var hai;
var sample = hai.test;//Invalid Will throw Type Error since base is undefined
bar.foo; // Invalid Will throw Referrence Error. Since bar is not even declared
</pre><br />
Try all these yourself<br />
<pre class='brush:javascript'>false == 'false'
false == null
false == ''
false == undefined
false == 0
false == Nan
false == 'false'
true == 'true'
true == '1'
false == '0'
''==0
</pre>And wonder :)<br />
<br />
I hope I'm Done :)Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0tag:blogger.com,1999:blog-4836497234580815703.post-5365672947124525102011-11-15T19:19:00.000+05:302012-08-06T19:35:07.288+05:30CQL(Cassandra Query Language) ReferenceHi,<br />
I think now I'm eligible to publish a blog post regd CQL. I wish this blog to be a tutorial rather a Syntax provider for various CQL queries<br />
<br />
<b>Points to remember</b><br />
1. CQL doesn't support Composite Types[likely to chage]<br />
2. CQL doesn't support Super columns<br />
3. Counter values are returned in native format [atleast in php/using cqlsh]<br />
<b><br />
Why should I prefer CQL?</b><br />
1. Readability<br />
2. Ease of use<br />
3. SQL like<br />
4. Stable<br />
<br />
<b>Support:</b><br />
PHP => <a href='http://itsallabtamil.blogspot.com/search/label/cassandra'> My Posts </a> using <a href="http://thobbs.github.com/phpcassa/">PHPCassa</a><br />
Python => Refer <a href='http://techdocs.acunu.com/v1.1/html/tutorial.html#installing-cql'> Here </a> and Download it <a href='http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/'> here </a><br />
Java => <a href='http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/'>JDBC Driver</a> and Example is <a href="http://stackoverflow.com/questions/7688571/cassandra-cql-jdbc-driver"> here </a><br />
Ruby => This might <a href='https://github.com/kreynolds/cassandra-cql'> help </a><br />
<br />
<b> Creating a Keyspace:</b><br />
<pre class="brush:sql">cqlsh> CREATE KEYSPACE sample WITH strategy_class = 'org.apache.cassandra.locator.SimpleStrategy'
... AND strategy_options:replication_factor = 2;
</pre>Note:<br />
: => Option Specifier <br />
<br />
<b>Use a Keyspace:</b><br />
<pre class="brush:sql">cqlsh> USE sample;
</pre>Note:<br />
Don't forget to USE before use<br />
'Sample' and 'sample' are different.<br />
<br />
<b> Create Column Family:</b><br />
<pre class="brush:sql">cqlsh> CREATE COLUMNFAMILY Test (date ascii PRIMARY KEY, name ascii, age int) WITH default_validation=ascii
... AND comparator=ascii
... AND replicate_on_write=true;
</pre><br />
<b>Insert Row:</b><br />
<pre class="brush:sql">cqlsh> INSERT INTO Test ('date', 'name', 'age') VALUES ('123', 'tamil', 12)
... USING CONSISTENCY ONE
... AND TTL 20;
</pre><br />
<b> Update Counter Row:</b><br />
<pre class="brush:sql">cqlsh> UPDATE COUNTERTEST SET 'samplecounter' = 'samplecounter'+5 WHERE KEY='testkey';
</pre><br />
<b>Update Standard Row:</b><br />
<pre class="brush:sql">cqlsh> UPDATE Test SET 'name'='Tamil' WHERE 'date'='123'
</pre>Note:<br />
We have named row key as 'date'<br />
If you specify KEY instead 'date' your terminal might knock with<br />
Bad Request: Expected key 'KEY' to be present in WHERE clause for 'Test'<br />
<br />
<br />
<b> Select:</b><br />
<pre class="brush:sql;">cqlsh> SELECT * FROM Test WHERE 'date'='123';
date | age | dept | desc | name | rollno |
123 | 12 | yyy | zzz | tamil | xxx |
cqlsh> SELECT 'a'..'f' FROM Test WHERE 'date'='123';
age | dept | desc |
12 | yyy | zzz |
cqlsh> SELECT FIRST 2 'a'..'z' FROM Test WHERE 'date'='123';
age | dept |
12 | yyy |
cqlsh> SELECT REVERSED 'z'..'a' FROM Test WHERE 'date'='123';
rollno | name | desc | dept | age |
xxx | tamil | zzz | yyy | 12 |
cqlsh> SELECT FIRST 2 REVERSED 'z'..'a' FROM Test WHERE 'date'='123';
rollno | name |
xxx | tamil |
cqlsh> SELECT * FROM Test;
date | age | name |
123 | 12 | yyy | zzz | tamil | xxx |
345 | 12 | pamil |
234 | 12 | camil |
cqlsh> SELECT * FROM Test LIMIT 2;
date | age | name |
123 | 12 | yyy | zzz | tamil | xxx |
345 | 12 | pamil |
--After some random insertions
cqlsh> SELECT * FROM Test where 'date' in ('123', '124', '125');
date | age | name |
123 | 12 | tamil |
124 | 12 | tamil |
125 | 12 | tamil |
</pre><b><br />
Truncate:</b><br />
<pre class="brush:sql">cqlsh> TRUNCATE Test;
</pre><b><br />
Drop:</b><br />
<pre class="brush:sql">cqlsh> DROP COLUMNFAMILY Test;
cqlsh> DROP KEYSPACE sample;
</pre><br />
Using Secondary Indexes we can query columns based on values rather by their names.<br />
<b> Creating Index </b><br />
<pre class="brush:sql">cqlsh> CREATE INDEX name_test_key ON Test (name);
</pre><br />
<b> Using the index </b><br />
<pre class="brush:sql">cqlsh> SELECT * FROM Test where name = 'tamil';
date | age | name |
127 | 13 | tamil |
123 | 12 | tamil |
124 | 12 | tamil |
cqlsh> SELECT * FROM Test where name = 'tamil' and age > 12;
date | age | name |
127 | 13 | tamil |
</pre><br />
<b>Note:</b> I'm able to query based on age's value too as there is an index existing on name<br />
So, I'm done :) Just refer this <a href='http://crlog.info/2011/09/17/cassandra-query-language-cql-v2-0-reference/'> guy's blog </a> for all constants, arguments and optionsTamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com3tag:blogger.com,1999:blog-4836497234580815703.post-3169549022176979282011-11-04T20:37:00.000+05:302012-03-14T21:49:23.894+05:30Cassandra CQL PHP Part 2<div dir="ltr" style="text-align: left;" trbidi="on">I have explained the way to execute CQL Queries from PHP via PHPCassa in my previous blogpost <a href="http://itsallabtamil.blogspot.com/2011/10/cassandra-cql-php.html">here</a> and tutorial on cql queries <a href="http://itsallabtamil.blogspot.com/2011/11/cqlcassandra-query-language-reference.html">here</a><br />
<br />
It was difficult for me to remember the syntax of update and select CQL queries for Cassandra. Hence I wrote wrappers for them which are listed below<br />
<br />
<b>Update Counter Query:</b><br />
<pre class="brush:php">/*
* $counterMap => Associative array of CounterColumn names and corresponding value for given $key
* Ex: UPDATE TestCounterFamily SET 'counter'='counter'+1, 'counter2'='counter2'+3 WHERE KEY='test'
*/
function generateUpdateCounterQuery($columnFamily, $counterMap, $key)
{
$colArgs = "";
foreach($counterMap as $counter => $value)
{
$colArgs=$colArgs."'".$counter."'='".$counter."'+".$value.", ";
}
$colArgs = rtrim($colArgs,", ");
return "UPDATE ".$columnFamily." SET ".$colArgs." WHERE KEY='".$key."'";
}
</pre><br />
<b>Update Standard Column Query</b><br />
<pre class="brush:php">/*
* $columnMap => Associative array of Column names and corresponding value for given $key
* Ex: UPDATE TestColumnFamily SET 'name'='abc', 'country'='IN' WHERE KEY='test'
*/
function generateUpdateStandardColumnQuery($columnFamily, $columnMap, $rowKey)
{
$colArgs = "";
foreach($columnMap as $columnKey => $value)
{
$colArgs=$colArgs."'".$columnKey."'='".$value."', ";
}
$colArgs = rtrim($colArgs,", ");
return "UPDATE ".$columnFamily." SET ".$colArgs." WHERE KEY='".$rowKey."'";
}
</pre><br />
<b> Select Column Query </b><br />
<pre class="brush:php">/*
* $column = Column to be selected from Cassandra $columnFamily
* Ex: SELECT 'name' FROM TestColumnFamily WHERE KEY='test'(Updated)
*/
function generateSelectQuery($columnFamily, $column, $key, $limit='-1', $reversed='0', $range=false)
{
if($limit=='-1')
{
if($reversed == '1' && $range)
{
return "SELECT REVERSED '".$column."' FROM ".$columnFamily." WHERE KEY = '".$key."'";
}
return "SELECT '".$column."' FROM ".$columnFamily." WHERE KEY = '".$key."'";
}
if($reversed=='0')
{
return "SELECT FIRST ".$limit." '".$column."' FROM ".$columnFamily." WHERE KEY = '".$key."'";
}
return "SELECT FIRST ".$limit." REVERSED '".$column."' FROM ".$columnFamily." WHERE KEY = '".$key."'";
}
</pre><br />
<b> Generate Range Queries </b><br />
<pre class="brush:php">function selectColumnRange($columnFamily, $from, $to, $key, $limit='-1', $reversed='0')
{
return $this->generateSelectQuery($columnFamily ,$from."'".".."."'".$to, $key, $limit, $reversed, $range=true);
}
</pre><br />
<b> Execute Selects and Updates </b><br />
<pre class="brush:php">function executeCQLSelect($query, $compression=cassandra_Compression::NONE)
{
$resultSet = $raw->client->execute_cql_query($query, $compression);
return $resultSet;
}
function executeCQLUpdate($query, $compression=cassandra_Compression::NONE)
{
$raw->client->execute_cql_query($query, $compression);
}
</pre><br />
Sample ColumnMap array would be like <br />
<pre class="brush:php">$columnMap = array("name"=>"test", "country"=>"IN")
</pre><br />
My solution to test ResultSet returned by Select Query<br />
<pre class="brush:php">function isResultNull($resultSet)
{
return (isset($resultSet->rows[0]) && $resultSet->rows[0] instanceof cassandra_CqlRow && count($resultSet->rows[0]->columns) > 0);
}
</pre><br />
Hope this helps :)</div>Tamil Selvan Raman Subramaniamhttp://www.blogger.com/profile/03026467443922242454noreply@blogger.com0