18 April 2016
A simple Apache Storm tutorial [Part 2: Implementing failsafes]
Continued from part1
If you really want to understand what the Value class is, what the Tuple class is etc., the best place to look, is not the tutorials on the internet. Look at the actual Storm source code.
It's available here: https://github.com/apache/storm
Go into the "storm-core/src/jvm/org/apache/storm" folder and have a look at those Java files. The code is very simple to understand and I promise you, it will be an enlightening experience.
Now, onto the ack and fail aspects of Storm.
Given below, is the exact same program as Part 1 of this tutorial. The added sections and sections that need your attention are highlighted.
BasicStorm.java:
package com.sdint.basicstorm;
import org.apache.storm.Config;
import java.util.concurrent.TimeUnit;
import org.apache.storm.LocalCluster;
import org.apache.storm.topology.TopologyBuilder;
public class BasicStorm {
public static void main(String[] cmdArgs) {
Config config = new Config();
//config.put(Config.TOPOLOGY_DEBUG, false);
config.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);
config.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 10);//alters the default 30 second of tuple timeout to 10 second
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("myDataSpout", new DataSpout());
builder.setBolt("proBolt", new ProcessingBolt()).shuffleGrouping("myDataSpout");
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("BasicStorm", config, builder.createTopology());
System.out.println("\n\n\nTopology submitted\n\n\n");
pause(120);//pause for 120 seconds during which the emitting of tuples will happen
//localCluster.killTopology("BasicStorm");
localCluster.shutdown();
}//main
public static void pause(int timeToPause_InSeconds) {
try {TimeUnit.SECONDS.sleep(timeToPause_InSeconds);}
catch (InterruptedException e) {System.out.println(e.getCause());}
}
}//class
DataSpout.java:
package com.sdint.basicstorm;
import java.util.Map;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DataSpout extends BaseRichSpout {
private TopologyContext context;
private SpoutOutputCollector collector;
//---logger
private final Logger logger = LoggerFactory.getLogger(DataSpout.class);
private boolean tupleAck = true;
private Long oldTupleValue;
@Override
public void open(Map map, TopologyContext tc, SpoutOutputCollector soc) {
this.context = tc;
this.collector = soc;
System.out.println("\n\n\nopen of DataSpout\n\n\n");
}
public DataSpout() {
System.out.println("\n\n\nDataSpout ctor called\n\n\n");
}//ctor
@Override
public void declareOutputFields(OutputFieldsDeclarer ofd) {
System.out.println("\n\n\ndeclareoutputfields of DataSpout\n\n\n");
ofd.declare(new Fields("line"));
}
@Override
public void nextTuple() {
System.out.println("\n\n\nnexttuple of DataSpout\n\n\n");
Long newTupleValue;
if (tupleAck) {
newTupleValue = System.currentTimeMillis() % 1000;
oldTupleValue = newTupleValue;
}
else {newTupleValue = oldTupleValue;}
this.collector.emit(new Values(newTupleValue), newTupleValue);
System.out.println("\n\n\nEmitting "+newTupleValue+"\n\n\n");
pause(1);
}
@Override
public void ack(Object msgId) {
System.out.println("\n\n\nAck received for DataSpout"+msgId+"\n\n\n");
tupleAck = true;
}
@Override
public void fail(Object msgId) {
System.out.println("\n\n\nFailed tuple msgID: "+msgId+"\n\n\n");
//replay logic should be here
tupleAck = false;
}
public void pause(int timeToPause_InSeconds) {
try {TimeUnit.SECONDS.sleep(timeToPause_InSeconds);}
catch (InterruptedException e) {System.out.println(e.getCause());}
}
}//class
ProcessingBolt.java:
package com.sdint.basicstorm;
import java.util.Map;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Tuple;
public class ProcessingBolt extends BaseRichBolt {
private OutputCollector collector;
@Override
public void declareOutputFields(OutputFieldsDeclarer ofd) {
System.out.println("\n\n\ndeclareOutputFields of ProcessingBolt called\n\n\n");
}
@Override
public void prepare(Map map, TopologyContext tc, OutputCollector oc) {
System.out.println("\n\n\nprepare of ProcessingBolt called\n\n\n");
collector = oc;
}
@Override
public void execute(Tuple tuple) {
System.out.println("\n\n\nTuple received in ProcessingBolt:"+tuple+" \n\n\n");
collector.ack(tuple);
}
}
Notice that this time when you run the program, the ack function in the Spout will get called whenever the Bolt executes the collector.ack(tuple); statement.
But suppose you comment out collector.ack(tuple);, then after a certain time period (normally 30 seconds, but in our program we made it 10 seconds), the fail function will get called.
This is how the Spout (and we) know whether a tuple has been received by the Bolt and acknowledged or not. The above program basically uses the System time as a Tuple and in case the Bolt does not acknowledge that it has received the Tuple, then the Spout sends the same old Tuple to the Bolt again.
And before getting into hardcore Storm programming, there is this important thing:
Apache Storm concepts you really need to know.
A simple Apache Storm tutorial [Part1]
Apache Storm is actually well documented. Problem is, you won't understand any of it until you actually try out some code (even if it's in the form of a nice explanation by Chandan Prakash), and there's a dearth of simple code available on the internet. NRecursions comes to your rescue :-)
To run this program, you can either do it with Gradle (which I've used mainly so that the jar dependency management would automatically be handled by Gradle) or you could simply create a normal Java project and manually add the necessary jar's. The jar's you'll need are:
Create a Gradle project named "BasicStorm" and create a source package named "com.sdint.basicstorm".
Within that package, create BasicStorm.java
To run this program, you can either do it with Gradle (which I've used mainly so that the jar dependency management would automatically be handled by Gradle) or you could simply create a normal Java project and manually add the necessary jar's. The jar's you'll need are:
- asm-5.0.3.jar
- bson4jackson-2.7.0.jar
- clojure-1.7.0.jar
- disruptor-3.3.2.jar
- kryo-3.0.3.jar
- log4j-api-2.1.jar
- log4j-core-2.1.jar
- log4j-over-slf4j-1.6.6.jar
- log4j-slf4j-impl-2.1.jar
- logback-classic-1.1.3.jar
- logback-core-1.1.3.jar
- logback-core-1.1.3.jar
- minlog-1.3.0.jar
- objeneiss-2.1.jar
- reflectasm-1.10.1.jar
- servlet-api-2.5.jar
- slf4j-api-1.7.12.jar
- storm-core-1.0.0.jar
Create a Gradle project named "BasicStorm" and create a source package named "com.sdint.basicstorm".
Within that package, create BasicStorm.java
package com.sdint.basicstorm;
import org.apache.storm.Config;
import java.util.concurrent.TimeUnit;
import org.apache.storm.LocalCluster;
import org.apache.storm.topology.TopologyBuilder;
public class BasicStorm {
public static void main(String[] cmdArgs) {
Config config = new Config();
//config.put(Config.TOPOLOGY_DEBUG, false);
config.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);
config.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 10);//alters the default 30 second of tuple timeout to 10 second
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("myDataSpout", new DataSpout());
builder.setBolt("proBolt", new ProcessingBolt()).shuffleGrouping("myDataSpout");
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("BasicStorm", config, builder.createTopology());
System.out.println("\n\n\nTopology submitted\n\n\n");
pause(120);//pause for 120 seconds during which the emitting of tuples will happen
//localCluster.killTopology("BasicStorm");
localCluster.shutdown();
}//main
public static void pause(int timeToPause_InSeconds) {
try {TimeUnit.SECONDS.sleep(timeToPause_InSeconds);}
catch (InterruptedException e) {System.out.println(e.getCause());}
}
}//class
and DataSpout.java
import org.apache.storm.Config;
import java.util.concurrent.TimeUnit;
import org.apache.storm.LocalCluster;
import org.apache.storm.topology.TopologyBuilder;
public class BasicStorm {
public static void main(String[] cmdArgs) {
Config config = new Config();
//config.put(Config.TOPOLOGY_DEBUG, false);
config.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);
config.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 10);//alters the default 30 second of tuple timeout to 10 second
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("myDataSpout", new DataSpout());
builder.setBolt("proBolt", new ProcessingBolt()).shuffleGrouping("myDataSpout");
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("BasicStorm", config, builder.createTopology());
System.out.println("\n\n\nTopology submitted\n\n\n");
pause(120);//pause for 120 seconds during which the emitting of tuples will happen
//localCluster.killTopology("BasicStorm");
localCluster.shutdown();
}//main
public static void pause(int timeToPause_InSeconds) {
try {TimeUnit.SECONDS.sleep(timeToPause_InSeconds);}
catch (InterruptedException e) {System.out.println(e.getCause());}
}
}//class
and DataSpout.java
package com.sdint.basicstorm;
import java.util.Map;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DataSpout extends BaseRichSpout {
private TopologyContext context;
private SpoutOutputCollector collector;
//---logger
private final Logger logger = LoggerFactory.getLogger(DataSpout.class);
@Override
public void open(Map map, TopologyContext tc, SpoutOutputCollector soc) {
this.context = tc;
this.collector = soc;
System.out.println("\n\n\nopen of DataSpout\n\n\n");
}
public DataSpout() {
System.out.println("\n\n\nDataSpout constructor called\n\n\n");
}//ctor
@Override
public void declareOutputFields(OutputFieldsDeclarer ofd) {
System.out.println("\n\n\ndeclareoutputfields of DataSpout\n\n\n");
ofd.declare(new Fields("line"));
}
@Override
public void nextTuple() {
System.out.println("\n\n\nnexttuple of DataSpout\n\n\n");
Long newTupleValue =System.currentTimeMillis() % 1000;
this.collector.emit(new Values(newTupleValue), newTupleValue);
System.out.println("\n\n\nEmitting "+newTupleValue+"\n\n\n");
pause(1);
}
public void pause(int timeToPause_InSeconds) {
try {TimeUnit.SECONDS.sleep(timeToPause_InSeconds);}
catch (InterruptedException e) {System.out.println(e.getCause());}}
}//class
and ProcessingBolt.java
import java.util.Map;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DataSpout extends BaseRichSpout {
private TopologyContext context;
private SpoutOutputCollector collector;
//---logger
private final Logger logger = LoggerFactory.getLogger(DataSpout.class);
@Override
public void open(Map map, TopologyContext tc, SpoutOutputCollector soc) {
this.context = tc;
this.collector = soc;
System.out.println("\n\n\nopen of DataSpout\n\n\n");
}
public DataSpout() {
System.out.println("\n\n\nDataSpout constructor called\n\n\n");
}//ctor
@Override
public void declareOutputFields(OutputFieldsDeclarer ofd) {
System.out.println("\n\n\ndeclareoutputfields of DataSpout\n\n\n");
ofd.declare(new Fields("line"));
}
@Override
public void nextTuple() {
System.out.println("\n\n\nnexttuple of DataSpout\n\n\n");
Long newTupleValue =System.currentTimeMillis() % 1000;
this.collector.emit(new Values(newTupleValue), newTupleValue);
System.out.println("\n\n\nEmitting "+newTupleValue+"\n\n\n");
pause(1);
}
public void pause(int timeToPause_InSeconds) {
try {TimeUnit.SECONDS.sleep(timeToPause_InSeconds);}
catch (InterruptedException e) {System.out.println(e.getCause());}}
}//class
and ProcessingBolt.java
package com.sdint.basicstorm;
import java.util.Map;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Tuple;
public class ProcessingBolt extends BaseRichBolt {
private OutputCollector collector;
@Override
public void declareOutputFields(OutputFieldsDeclarer ofd) {
System.out.println("\n\n\ndeclareOutputFields of ProcessingBolt called\n\n\n");
}
@Override
public void prepare(Map map, TopologyContext tc, OutputCollector oc) {
System.out.println("\n\n\nprepare of ProcessingBolt called\n\n\n");
collector = oc;
}
@Override
public void execute(Tuple tuple) {
System.out.println("\n\n\nTuple received in ProcessingBolt:"+tuple+" \n\n\n");
collector.ack(tuple);
}
}
Your build.gradle file would look like this (if you choose to create a Gradle project. You won't need this if you're creating a simple Java project):
apply plugin: 'java'
apply plugin: 'eclipse'
defaultTasks 'jar'
jar {
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'com.sdint.basicstorm.BasicStorm'
}
}
sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
if (!hasProperty('mainClass')) {
ext.mainClass = 'com.sdint.basicstorm.BasicStorm'
}
repositories {
mavenCentral()
}
dependencies {
//---apache storm
compile 'org.apache.storm:storm-core:1.0.0' //compile 'org.apache.storm:storm-core:0.10.0'
//---logging
compile "org.slf4j:slf4j-api:1.7.12"
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'ch.qos.logback:logback-core:1.1.3'
testCompile group: 'junit', name: 'junit', version: '4.10'
}
Hope you've already read a little about how the Spout's and Bolt's work in Storm.
This is what happens in BasicStorm:
Try tweaking the values here and there to find out how the program works. Try substituting some other value in place of the Long for the Tuple. Try substituting it with a class object. Remember that if you substitute it like that, you'll have to extend that class with Serializable.
One more thing to try out:
Try commenting out collector.ack(tuple); in ProcessingBolt.java. You'll basically not be telling the Spout that the tuple has been received by the Bolt. So after some time, the Spout will emit the tuple again. The interval of time the Spout waits for an acknowledgement (ack) is normally 30 seconds, but if you scroll up, you'll see that in main() we had set the time to 10 seconds (config.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 10);), so the Spout will wait just ten seconds before emitting the tuple again.
import java.util.Map;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Tuple;
public class ProcessingBolt extends BaseRichBolt {
private OutputCollector collector;
@Override
public void declareOutputFields(OutputFieldsDeclarer ofd) {
System.out.println("\n\n\ndeclareOutputFields of ProcessingBolt called\n\n\n");
}
@Override
public void prepare(Map map, TopologyContext tc, OutputCollector oc) {
System.out.println("\n\n\nprepare of ProcessingBolt called\n\n\n");
collector = oc;
}
@Override
public void execute(Tuple tuple) {
System.out.println("\n\n\nTuple received in ProcessingBolt:"+tuple+" \n\n\n");
collector.ack(tuple);
}
}
Your build.gradle file would look like this (if you choose to create a Gradle project. You won't need this if you're creating a simple Java project):
apply plugin: 'java'
apply plugin: 'eclipse'
defaultTasks 'jar'
jar {
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'com.sdint.basicstorm.BasicStorm'
}
}
sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
if (!hasProperty('mainClass')) {
ext.mainClass = 'com.sdint.basicstorm.BasicStorm'
}
repositories {
mavenCentral()
}
dependencies {
//---apache storm
compile 'org.apache.storm:storm-core:1.0.0' //compile 'org.apache.storm:storm-core:0.10.0'
//---logging
compile "org.slf4j:slf4j-api:1.7.12"
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'ch.qos.logback:logback-core:1.1.3'
testCompile group: 'junit', name: 'junit', version: '4.10'
}
Hope you've already read a little about how the Spout's and Bolt's work in Storm.
This is what happens in BasicStorm:
- The moment a Spout or Bolt is instantiated, its declareOutputFields function gets called. For our simple program we don't need to know what it is, so let's ignore it for now.
- When the topology is submitted to Storm, the open function gets called for Spouts, and this function gets called only once for a Spout instance.
- For Bolts, the equivalent of open is the prepare function which gets called. You can use open and prepare to do initializations, declarations etc. for your program.
- After submitting the topology, we pause for a while in main() (pause(120);) so that Storm would get time to run the topology. This is the time during which Storm calls nextTuple() of the Spout, and when the Spout emits a Tuple, the Tuple is sent to the Bolt (because in main() we configured the Bolt to receive Tuples from the Spout. See the line builder.setBolt("proBolt", new ProcessingBolt()).shuffleGrouping("myDataSpout");).
- When the Bolt receives the value, the execute() function of the Bolt is called.
- BasicStorm is designed for a simple task. DataSpout emits a Long value (it's a Tuple), ProcessingBolt receives it and ProcessingBolt acknowledges (the collector.ack(tuple); line) that it has received the Long value and that the data processing for the tuple is complete.
- When DataSpout receives the acknowledgement, it calls nextTuple() again and another tuple gets emitted.
- This process keeps going on for the 120 seconds we have paused the main() thread for. After that, the topology shuts down.
Try tweaking the values here and there to find out how the program works. Try substituting some other value in place of the Long for the Tuple. Try substituting it with a class object. Remember that if you substitute it like that, you'll have to extend that class with Serializable.
One more thing to try out:
Try commenting out collector.ack(tuple); in ProcessingBolt.java. You'll basically not be telling the Spout that the tuple has been received by the Bolt. So after some time, the Spout will emit the tuple again. The interval of time the Spout waits for an acknowledgement (ack) is normally 30 seconds, but if you scroll up, you'll see that in main() we had set the time to 10 seconds (config.put(Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS, 10);), so the Spout will wait just ten seconds before emitting the tuple again.
Continued in Part 2
06 April 2016
A comfortable Git branching model
Git has a very flexible approach toward branching, and workflows. The best I've seen yet.
Novices would probably be happy using the popular branching model Vincent Driessen has shown on his webpage: http://nvie.com/posts/a-successful-git-branching-model/
I've learnt from and liked Vincent's work, but during the course of working with the branching model, it has been more comfortable to use a slightly different model, especially when collaborating with other developers.
What I propose to be different...
...is simply that instead using the master branch to maintain the "stable" version of the code, it is more comfortable to have the master branch as the branch that the entire team collaborates on.
A separate branch named "stable" (see; even the name is more appropriate than 'master') is created, which is also pushed to the remote/blessed repository, and that's the branch that keeps your stable version of the code that is ready for release.
It's not only about the comfort that the master branch affords you for collaborative development: ie: simply using "git pull" instead of "git pull origin development" etc.
It's also the fact that you'll have to do fewer merges between branches, which could end up looking like this:
The above screenshot is from GitUp. One of the best Git clients I've seen. Once you do a merge, you can actually undo it too (only available for MacOS though. When I wanted to port it to Linux myself, I saw the developers post that he's used too much of Objective C code for the graphics to be able to port it).
Novices would probably be happy using the popular branching model Vincent Driessen has shown on his webpage: http://nvie.com/posts/a-successful-git-branching-model/
I've learnt from and liked Vincent's work, but during the course of working with the branching model, it has been more comfortable to use a slightly different model, especially when collaborating with other developers.
What I propose to be different...
...is simply that instead using the master branch to maintain the "stable" version of the code, it is more comfortable to have the master branch as the branch that the entire team collaborates on.
A separate branch named "stable" (see; even the name is more appropriate than 'master') is created, which is also pushed to the remote/blessed repository, and that's the branch that keeps your stable version of the code that is ready for release.
It's not only about the comfort that the master branch affords you for collaborative development: ie: simply using "git pull" instead of "git pull origin development" etc.
It's also the fact that you'll have to do fewer merges between branches, which could end up looking like this:
The above screenshot is from GitUp. One of the best Git clients I've seen. Once you do a merge, you can actually undo it too (only available for MacOS though. When I wanted to port it to Linux myself, I saw the developers post that he's used too much of Objective C code for the graphics to be able to port it).
29 March 2016
How to play LAN games using a wireless router
This is for people owning a WiFi router, who are just looking to setup a simple LAN game on their personal LAN network. Not via internet.
Assuming you have two systems: A PC and a laptop, with two different versions of Windows OS. Let's say Windows XP and Windows 8.
Setting the IP address:
- Connect the wireless router to the PC using a LAN cable and connect it to a power source.
- Switch on the PC.
- Goto Windows network settings, click on the network properties and in IPv4, set the IP address of the PC to 192.168.1.10. Set the subnet mask to 255.255.255.0.
- Switch on the laptop and allow it to connect to the wireless connection from the router.
- Goto the laptop's Windows network settings, click on the network properties and in IPv4, set the IP address to 192.168.1.11. Set the subnet mask to 255.255.255.0.
- Like this you could add a few more computers if you want, ensuring that you set the IP address to a different number.
Ensuring that the computers can talk to each other:
- Temporarily switch off the firewalls on both computers (and ensure that they aren't connected to the internet for safety reasons). You could also keep the firewall on and allow the specific ports that the LAN games require for communication, but switching the firewall off is the easiest way.
- Open up a DOS terminal (cmd.exe) in both computers.
- In the PC, type ping 192.168.1.11
- In the laptop, type ping 192.168.1.10
- In both terminals, you should see a successful ping happening with no losses. If it happens, then you are ready to start gaming. If not, you need to check why the networks aren't able to connect with each other.
Now open up the game on both computers and enjoy!
28 March 2016
13 March 2016
Waterproofing and cement
When it comes to finding good workmanship in India for plumbing, masonry or electrical work, it's hard to find good people (I hear HR departments in all companies face that difficulty too).
Once you find people with good workmanship, you are at times presented with the danger of them ripping you off.
Insider lingo
Something that helps in such situations, is in knowing what are called "insider terms". When giving your car for servicing, if the mechanic starts speaking about the "manifold" and you don't know what that means, he's likely to recommend cleaning the pipes that lead to and lead out of it. What he doesn't tell you is that it's going to cost a small fortune to unmount it and clean it. But if you know the lingo and the recommended servicing mentioned in the manual, you can flatly refuse the cleaning which is actually un-necessary.
Same goes with other small work. A mason may tell you about the "white cement" (with an expression on his face that it's something very great) he's going to use on your house, along with waterproofing cement and some other cement. But he does not want to be questioned about anything and he's going to charge a fixed price.
Don't fall for it. Find out. Also search for complaints on Mouthshut.com or one of the many consumer complaints forums.
Cement is...
Unless you know what cement is, why sand is added to it and what kind of cement can give you proper waterproofing, the contractor or the mason can rip you off, by citing the high cost/quality of the materials they use or the so-called extra care they take to do the work very well.
Here are some things you need to know:
How hydraulic cement is created:
Put simply, limestone is crushed to a powder and heated at 3500 degrees Celsius. This causes the Hydrogen molecules in it to escape, and the resulting powder is cement. During construction, you add water to the cement, and the hydrogen from the water combines with the cement to become hard. One such hydraulic cement is called "Portland cement". Hydraulic cements can be used to seal even swimming pools. Some of these cements can be used even underwater.
Mike Haduck explains it well, and I recommend his other videos too where he explains various types of masonry work.
Why sand is added to cement:
Sand has Silica, which increases the strength of the cement. Sand also happens to be an additive, which like other additives (fiber-glass, gravel, stones), adds to the compressive strength of the cement. Basically, too much sand or too much cement can make the resultant concrete/mortar brittle.
Cement is basically the binder that binds all the aggregates like sand and stone into a solid mass called concrete.
What is concrete and mortar?
Cement is just the dry powder you get. When it's added to water and sand, it becomes hard, and that's called concrete.
If you have to use cement with brick-work, make sure you use mortar instead of Portland concrete. For side-walks, patio's, highways, swimming pools, roof-work etc, Portland is better.
How much of waterproofing liquid should I add to the cement?
You add waterproofing liquid to the water; not the cement. The liquid will be miscible and you then add the mixture to the cement. The packet will have instructions on what ratio to follow. Generally, the waterproofing liquid should not be more than 2% to 5% of the cement. There are people who say that if the quality of the sand is not good enough, then it's ok to add upto 20% of the liquid.
Careful though, since the purpose of the waterproofing liquid is just to give the cement more plasticity. If you add too much, the cement will lose its strength. Hydraulic concrete by itself has a sufficient amount of waterproofing property. Make sure you cure it well.
What is curing and how much of it should I do?
The hardening of concrete happens by a process called "hydration", during which the mineral hydrates solidify. For hydraulic cements like Portland cement, the concrete hardens better not if you leave it alone to dry, but it hardens better if there's moisture present during the hardening. Remember I mentioned that the hydrogen molecules from the water go back to the cement and make it hard?
If you don't have curing oils/compounds or plastic shields, then the simpler way of ensuring that the moisture remains with the cement, is to use a gunny bag or cloth that's placed on the cement and to pour water over it. Make sure the moisture is retained for around 28 days, as this is the curing time that it is designed for. Of course, this may also vary based on the additives and mixture chosen.
What is so great about white cement?
Actually, nothing. Grey cement and white cement have almost the same chemical composition. All cements when manufactured, are white. It's the additives that change the colour of the cement. White cement has certain ferrous or other metallic oxides added to it. For decorative purposes, other additives may be added to give the white cement some other colour.
When you know just this much of information and speak to a mason, you'll see that they don't really know much about their job. They've been taught through the years to use certain materials and ratios, but they have no clue why. It's always better to
Find an engineer or a contractor who:
Search for people with knowledge. Get people who don't rip you off.
Your best bet is in learning what needs to be learnt and consulting with many contractors. Don't wait for the day you badly need plumbing/masonry work to be done. Search for these people even when you don't have any emergency, so that you'll get the right person during an emergency.
Once you find people with good workmanship, you are at times presented with the danger of them ripping you off.
Insider lingo
Something that helps in such situations, is in knowing what are called "insider terms". When giving your car for servicing, if the mechanic starts speaking about the "manifold" and you don't know what that means, he's likely to recommend cleaning the pipes that lead to and lead out of it. What he doesn't tell you is that it's going to cost a small fortune to unmount it and clean it. But if you know the lingo and the recommended servicing mentioned in the manual, you can flatly refuse the cleaning which is actually un-necessary.
Same goes with other small work. A mason may tell you about the "white cement" (with an expression on his face that it's something very great) he's going to use on your house, along with waterproofing cement and some other cement. But he does not want to be questioned about anything and he's going to charge a fixed price.
Don't fall for it. Find out. Also search for complaints on Mouthshut.com or one of the many consumer complaints forums.
Cement is...
Unless you know what cement is, why sand is added to it and what kind of cement can give you proper waterproofing, the contractor or the mason can rip you off, by citing the high cost/quality of the materials they use or the so-called extra care they take to do the work very well.
Here are some things you need to know:
How hydraulic cement is created:
Put simply, limestone is crushed to a powder and heated at 3500 degrees Celsius. This causes the Hydrogen molecules in it to escape, and the resulting powder is cement. During construction, you add water to the cement, and the hydrogen from the water combines with the cement to become hard. One such hydraulic cement is called "Portland cement". Hydraulic cements can be used to seal even swimming pools. Some of these cements can be used even underwater.
Mike Haduck explains it well, and I recommend his other videos too where he explains various types of masonry work.
Why sand is added to cement:
Sand has Silica, which increases the strength of the cement. Sand also happens to be an additive, which like other additives (fiber-glass, gravel, stones), adds to the compressive strength of the cement. Basically, too much sand or too much cement can make the resultant concrete/mortar brittle.
Cement is basically the binder that binds all the aggregates like sand and stone into a solid mass called concrete.
What is concrete and mortar?
- Cement + water + sand + gravel = concrete
- Cement + water + sand = plaster
- Cement + water + sand + lime = mortar
Cement is just the dry powder you get. When it's added to water and sand, it becomes hard, and that's called concrete.
If you have to use cement with brick-work, make sure you use mortar instead of Portland concrete. For side-walks, patio's, highways, swimming pools, roof-work etc, Portland is better.
How much of waterproofing liquid should I add to the cement?
You add waterproofing liquid to the water; not the cement. The liquid will be miscible and you then add the mixture to the cement. The packet will have instructions on what ratio to follow. Generally, the waterproofing liquid should not be more than 2% to 5% of the cement. There are people who say that if the quality of the sand is not good enough, then it's ok to add upto 20% of the liquid.
Careful though, since the purpose of the waterproofing liquid is just to give the cement more plasticity. If you add too much, the cement will lose its strength. Hydraulic concrete by itself has a sufficient amount of waterproofing property. Make sure you cure it well.
What is curing and how much of it should I do?
The hardening of concrete happens by a process called "hydration", during which the mineral hydrates solidify. For hydraulic cements like Portland cement, the concrete hardens better not if you leave it alone to dry, but it hardens better if there's moisture present during the hardening. Remember I mentioned that the hydrogen molecules from the water go back to the cement and make it hard?
If you don't have curing oils/compounds or plastic shields, then the simpler way of ensuring that the moisture remains with the cement, is to use a gunny bag or cloth that's placed on the cement and to pour water over it. Make sure the moisture is retained for around 28 days, as this is the curing time that it is designed for. Of course, this may also vary based on the additives and mixture chosen.
What is so great about white cement?
Actually, nothing. Grey cement and white cement have almost the same chemical composition. All cements when manufactured, are white. It's the additives that change the colour of the cement. White cement has certain ferrous or other metallic oxides added to it. For decorative purposes, other additives may be added to give the white cement some other colour.
When you know just this much of information and speak to a mason, you'll see that they don't really know much about their job. They've been taught through the years to use certain materials and ratios, but they have no clue why. It's always better to
Find an engineer or a contractor who:
- Knows the what and why of the ratios of materials to mix.
- Patiently explains the process to you and allows you to ask doubts.
- Allows you to supervise the cementing process (though they prefer it if you stay out of their hair when the work is going on)
- Asks his workers to use protective gloves and masks (the contents of cement and waterproofing agents are harmful chemicals)
Search for people with knowledge. Get people who don't rip you off.
04 March 2016
Generate a gitignore for Netbeans, Eclipse, IntelliJ Idea, Gradle or anything else!
I've written about gitignore for Netbeans, but recently came across something much better. There's actually a gitignore generator which can generate the file and folder list that Git should ignore. It's available for 255 types of IDE's, OS'es etc.
Either just type the name of the IDE, OS or programming language and click "Generate"...
OR
... install the commandline version of it and at the terminal, simply type:
gi <IDE or language or OS name>
and the custom gitignore gets generated.
or if you want to directly generate the file, just add the redirection operator:
gi <IDE or language or OS name> >> .gitignore
or if you don't want to generate specific gitignores for every project, simply generate a global one.
Eg:
gi linux, netbeans >> ~/.gitignore_global
As simple as that. It's quite amazing that someone took the time to actually create a gitignore generator. Thoughtful, and very much a gem for programmers around the world!
A little video if you still need help:
Either just type the name of the IDE, OS or programming language and click "Generate"...
OR
... install the commandline version of it and at the terminal, simply type:
gi
and the custom gitignore gets generated.
or if you want to directly generate the file, just add the redirection operator:
gi
or if you don't want to generate specific gitignores for every project, simply generate a global one.
Eg:
gi linux, netbeans >> ~/.gitignore_global
As simple as that. It's quite amazing that someone took the time to actually create a gitignore generator. Thoughtful, and very much a gem for programmers around the world!
A little video if you still need help:
28 February 2016
National science day: The cultivation of scientific temper
Today was Breakthrough Society's celebration of National Science Day and the observation of the "Cultivation of scientific temper". It included many school children and adults who were invited to the Raman Research Institute at Bangalore for a seminar and an exhibition.
It was my first visit to the campus, and I just loved the beauty of it. Reminded me of Bangalore, the way it was before concrete, asphalt and smoke took over the city!
The conference touched upon topics of scientific importance, about the need for research in India, the realization that people should have about science and the way it impacts humanity and an appeal that people go through some trouble in life; even if it involves some amount of struggle, so that their research and discoveries can bring greater good to humanity.
The seminar was followed by a documentary on Dr.C.V.Raman's life.
and a visit to the science museum, where there were various exhibits and publications of Dr.C.V.Raman.
We were shown how Dr.Raman (at the age of 16 or 17), had questioned why the Veena sounded like a human, and pursued the question. Even though Helmholtz had said that a plucked string could oscillate in only an odd number of ways (1, 3 or 5) etc..., Dr.Raman went on to prove that the Veena could even oscillate in even numbers, hence producing sounds similar to that of a human. This was because Helmholtz had experimented with a Violin, whereas the strings of a Veena are strung very differently, and when plucked, they oscillate differently.
Dr.Raman also dropped a metal bearing on glass and noticed the circular crack it made on impact. He tried the same on quartz crystals and noticed that here, the cracks were triangular in shape. Typical scientist :-)
The science museum has a large collection of objects he studied and collected. Said to be the largest collection any scientist has. Photos were forbidden since they said that if the photos were shared on social media, that would dampen the curiosity of the children. I disagree. The collection is so unique and amazing, that people would actually want to send their kids to actually see it. Believe me; there are no photographs that can capture the glimmer and wonder of those stones which are captured by the eye.
Also on display were some interesting quotes:
There was also an interesting quote from Einstein, which I followed up on:
But perhaps one of the most important quotes the community was missing out on, was this one:
It's not really about the survival of the strongest or the most intelligent. It is about the one that is most responsive to change.
My view
We see many protests in our country about growing intolerance and the lack of promotion of science. Makes me wonder why this happens. Many decades ago, it was the will of certain curious people which helped them make discoveries, helped the world to advance and brought pride to the nation. Any government would be happy to encourage such people and I believe this is why science was given importance. This is why we had impressive research institutes and dedicated people.
As the years passed by, did something else create more value for the nation? Did research cease to add as much value as something else? Did our nation become self-reliant enough that it no longer needed science? Is it more economical to purchase a technology from a neighboring nation than to invest in our own research? Does the work of private enterprises add more value to our nation?
As Darwin's quote in the above picture says; it is the species that is most responsive to change that survives. Has our scientific community adapted to the changes? We live at an age that has seen more peace on Earth than in historical times. Is this an age where the entire world works as one (except North Korea)? Where research in basic sciences, can be done at select countries so that other countries can focus on other things? Does a country really need to worry that it is not doing enough research?
What exactly is the bigger picture here? I'm quite sure that if a nation needed more research, the government would have actively pursued it. If a government isn't doing so, there's a reason. What is that reason?
Is our advanced, industrialized society really deteriorating (as Einstein said) and becoming focused on the trivialities of life?
I believe things will change. Not by dissent; not by protest. The change will be brought about by a mind that conceives such a thought, that it would alter the very way we live our lives. In the same way that a hundred years ago, everyone who predicted the future did not in the least bit take into account or conceptualize the advent of software.
There is hope.
It was my first visit to the campus, and I just loved the beauty of it. Reminded me of Bangalore, the way it was before concrete, asphalt and smoke took over the city!
The conference touched upon topics of scientific importance, about the need for research in India, the realization that people should have about science and the way it impacts humanity and an appeal that people go through some trouble in life; even if it involves some amount of struggle, so that their research and discoveries can bring greater good to humanity.
The seminar was followed by a documentary on Dr.C.V.Raman's life.
and a visit to the science museum, where there were various exhibits and publications of Dr.C.V.Raman.
We were shown how Dr.Raman (at the age of 16 or 17), had questioned why the Veena sounded like a human, and pursued the question. Even though Helmholtz had said that a plucked string could oscillate in only an odd number of ways (1, 3 or 5) etc..., Dr.Raman went on to prove that the Veena could even oscillate in even numbers, hence producing sounds similar to that of a human. This was because Helmholtz had experimented with a Violin, whereas the strings of a Veena are strung very differently, and when plucked, they oscillate differently.
Dr.Raman also dropped a metal bearing on glass and noticed the circular crack it made on impact. He tried the same on quartz crystals and noticed that here, the cracks were triangular in shape. Typical scientist :-)
The science museum has a large collection of objects he studied and collected. Said to be the largest collection any scientist has. Photos were forbidden since they said that if the photos were shared on social media, that would dampen the curiosity of the children. I disagree. The collection is so unique and amazing, that people would actually want to send their kids to actually see it. Believe me; there are no photographs that can capture the glimmer and wonder of those stones which are captured by the eye.
Also on display were some interesting quotes:
There was also an interesting quote from Einstein, which I followed up on:
I have now reached the point where I may indicate briefly what to me constitutes the essence of the crisis of our time. It concerns the relationship of the individual to society. The individual has become more conscious than ever of his dependence upon society. But he does not experience this dependence as a positive asset, as an organic tie, as a protective force, but rather as a threat to his natural rights, or even to his economic existence. Moreover, his position in society is such that the egotistical drives of his make-up are constantly being accentuated, while his social drives, which are by nature weaker, progressively deteriorate. All human beings, whatever their position in society, are suffering from this process of deterioration. Unknowingly prisoners of their own egotism, they feel insecure, lonely, and deprived of the naive, simple, and unsophisticated enjoyment of life. Man can find meaning in life, short and perilous as it is, only through devoting himself to society.
The economic anarchy of capitalist society as it exists today is, in my opinion, the real source of the evil. We see before us a huge community of producers the members of which are unceasingly striving to deprive each other of the fruits of their collective labor—not by force, but on the whole in faithful compliance with legally established rules. In this respect, it is important to realize that the means of production—that is to say, the entire productive capacity that is needed for producing consumer goods as well as additional capital goods—may legally be, and for the most part are, the private property of individuals.
But perhaps one of the most important quotes the community was missing out on, was this one:
It's not really about the survival of the strongest or the most intelligent. It is about the one that is most responsive to change.
My view
We see many protests in our country about growing intolerance and the lack of promotion of science. Makes me wonder why this happens. Many decades ago, it was the will of certain curious people which helped them make discoveries, helped the world to advance and brought pride to the nation. Any government would be happy to encourage such people and I believe this is why science was given importance. This is why we had impressive research institutes and dedicated people.
It created value for the nation.
As the years passed by, did something else create more value for the nation? Did research cease to add as much value as something else? Did our nation become self-reliant enough that it no longer needed science? Is it more economical to purchase a technology from a neighboring nation than to invest in our own research? Does the work of private enterprises add more value to our nation?
As Darwin's quote in the above picture says; it is the species that is most responsive to change that survives. Has our scientific community adapted to the changes? We live at an age that has seen more peace on Earth than in historical times. Is this an age where the entire world works as one (except North Korea)? Where research in basic sciences, can be done at select countries so that other countries can focus on other things? Does a country really need to worry that it is not doing enough research?
What exactly is the bigger picture here? I'm quite sure that if a nation needed more research, the government would have actively pursued it. If a government isn't doing so, there's a reason. What is that reason?
Is our advanced, industrialized society really deteriorating (as Einstein said) and becoming focused on the trivialities of life?
I believe things will change. Not by dissent; not by protest. The change will be brought about by a mind that conceives such a thought, that it would alter the very way we live our lives. In the same way that a hundred years ago, everyone who predicted the future did not in the least bit take into account or conceptualize the advent of software.
There is hope.
27 February 2016
Descriptive names
We've all been through our initial programming lessons, creating for loops as for(int i = 0; i<10; ++i) and so on. float s = d / t.
Variable names didn't matter much then.
The confusion begins, when you enter the professional world, write large programs, forget about them and months later, look at the code and wonder what in the world you had written long back. Class names, variable names and function names don't make any sense at all!!!
If you took care to write comments, then they are a saving grace, but only for a while.
Which of these would make more sense to you?
//check if customer age is equal to threshold
void check(double v)
{
if (val == v) {print("yes");} else {print("no");}
}
or
void checkIfCustomerAgeIsEqualToAgeThreshold(double customerAge)
{
if (ageThreshold == customerAge) {print("yes");} else {print("no");}
}
See the difference? No need of comments. No confusion. You understand what the function and variables are there for, just by looking at the code.
The other big advantage is that if you decided to do some refactoring, you wouldn't have to bother changing any comments, because the class/function/variable name itself is the comment!
Same goes with macros.
I see a lot of C++ programmers using...
#if 0
//some code
#endif
...to temporarily deactivate some code. If these programmers get hit by a bus or even if they look at the code many years later, they won't have a clue of why the code was deactivated and whether it is ok to simply delete it.
What if they used this instead:
#ifdef YEAR_CALCULATION_CODE_TEMPORARILY_DEACTIVATED_DONT_DELETE
//some code
#endif
or
#ifdef CODE_FOR_DEBUGGING_DELETEME_ANYTIME
or
#ifdef SWITCH_ON_COLOR_OUTPUT
Same goes with class names. Which makes more sense?:
class Filter{}
class MicroFilter extends Filter {}
or
class AirFilterSuperclass {}
class SpecializedMicroFilterOfCompanyABC extends AirFilterSuperclass {}
Variable names didn't matter much then.
The confusion begins, when you enter the professional world, write large programs, forget about them and months later, look at the code and wonder what in the world you had written long back. Class names, variable names and function names don't make any sense at all!!!
If you took care to write comments, then they are a saving grace, but only for a while.
Which of these would make more sense to you?
//check if customer age is equal to threshold
void check(double v)
{
if (val == v) {print("yes");} else {print("no");}
}
or
void checkIfCustomerAgeIsEqualToAgeThreshold(double customerAge)
{
if (ageThreshold == customerAge) {print("yes");} else {print("no");}
}
See the difference? No need of comments. No confusion. You understand what the function and variables are there for, just by looking at the code.
The other big advantage is that if you decided to do some refactoring, you wouldn't have to bother changing any comments, because the class/function/variable name itself is the comment!
Same goes with macros.
I see a lot of C++ programmers using...
#if 0
//some code
#endif
...to temporarily deactivate some code. If these programmers get hit by a bus or even if they look at the code many years later, they won't have a clue of why the code was deactivated and whether it is ok to simply delete it.
What if they used this instead:
#ifdef YEAR_CALCULATION_CODE_TEMPORARILY_DEACTIVATED_DONT_DELETE
//some code
#endif
or
#ifdef CODE_FOR_DEBUGGING_DELETEME_ANYTIME
or
#ifdef SWITCH_ON_COLOR_OUTPUT
Same goes with class names. Which makes more sense?:
class Filter{}
class MicroFilter extends Filter {}
or
class AirFilterSuperclass {}
class SpecializedMicroFilterOfCompanyABC extends AirFilterSuperclass {}
- It makes a world of a difference to the person who maintains the code.
- It makes another world of a difference to the person who reviews your code.
- And it makes an entirely different world of a difference to the business that profits because developers, tech leads and QA teams spent lesser time figuring out the code and spent more time in being able to create a splendid product!
08 February 2016
22 January 2016
Aha!
Continued from the previous Aha!
The game of life
Share with this link
Choices! Choices!
Share with this link
12 January 2016
Files and folders to add to gitignore for a Netbeans project
You're obviously on this page because you're a Netbeans fan. Congrats for choosing it over Eclipse!
When it came to creating a .gitignore file for my Netbeans project, it was hard to find resources on the internet to figure it out. Needing to push and pull to a Git repository meant that I shouldn't mess up my colleague's or my project settings, but still be able to share code.
So after some trial and error, these are the files I figured that need to be added to .gitignore.
/.project
*.o
*.o.d
/build/
/dist/
/lib/
/nbproject/private/
/nbproject/Makefile-Debug.mk
/nbproject/Makefile-impl.mk
/nbproject/Makefile-Release.mk
/nbproject/Makefile-variables.mk
When it came to creating a .gitignore file for my Netbeans project, it was hard to find resources on the internet to figure it out. Needing to push and pull to a Git repository meant that I shouldn't mess up my colleague's or my project settings, but still be able to share code.
So after some trial and error, these are the files I figured that need to be added to .gitignore.
/.project
*.o
*.o.d
/build/
/dist/
/lib/
/nbproject/private/
/nbproject/Makefile-Debug.mk
/nbproject/Makefile-impl.mk
/nbproject/Makefile-Release.mk
/nbproject/Makefile-variables.mk
/nbproject/Package-Debug.bash
/nbproject/Package-Release. bash
.dep.inc
DefaultComponent.mak
DefaultConfig.cg_info
MainDefaultComponent.cpp
MainDefaultComponent.h
/nbproject/Package-Release.
.dep.inc
DefaultComponent.mak
DefaultConfig.cg_info
MainDefaultComponent.cpp
MainDefaultComponent.h
Some interesting trivia about the Netbeans-Eclipse war from James Gosling himself: http://nrecursions.blogspot.com/2014/07/preview-your-webpage-realtime-while.html#useanyideyoulike
03 January 2016
A bashrc for Windows!!!
Today I came across a script I had written long ago and had completely forgotten about. Once you start using Linux, you'd want pretty much the same functionality in Windows. So I had created a bashrc equivalent for Windows.
Create a file named WindowsBashrc.cmd and follow the instructions in the comments below (REM is the short form for "Remark", and it's the equivalent of a commented out line. REM is used in BASIC and Windows batch files for commenting out lines). These are the steps.
@echo off
REM This has to be enabled in [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor]
REM "AutoRun"=C:\pathToYourFile\WindowsBashrc.cmd
REM It basically makes this script run whenever a command window is started
@echo "Hi Nav. Missed you! :)"
@doskey ls=dir
@doskey f="cd.."
@doskey ff="cd..;cd.."
@doskey fff="cd..;cd..;cd.."
@doskey ffff="cd..;cd..;cd..;cd.."
@d:
Create a file named WindowsBashrc.cmd and follow the instructions in the comments below (REM is the short form for "Remark", and it's the equivalent of a commented out line. REM is used in BASIC and Windows batch files for commenting out lines). These are the steps.
@echo off
REM This has to be enabled in [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor]
REM "AutoRun"=C:\pathToYourFile\WindowsBashrc.cmd
REM It basically makes this script run whenever a command window is started
@echo "Hi Nav. Missed you! :)"
@doskey ls=dir
@doskey f="cd.."
@doskey ff="cd..;cd.."
@doskey fff="cd..;cd..;cd.."
@doskey ffff="cd..;cd..;cd..;cd.."
@d:
btw, in Linux, thse are some handy bashrc aliases you can use: http://nrecursions.blogspot.com/2010/09/setting-up-your-bash-prompt-for-colours.html
02 January 2016
Ugly Indian: The UFO project
During the past many months, Bangaloreans began seeing the pillars of flyovers all across Bangalore getting a snazzy makeover. While I have participated in and blogged about other Ugly Indian projects...
...this UFO (Under The Flyover) project made me wonder how they painted it so neatly.
Turns out that before the orange paint was applied, the flyover pillars were covered with posters from people who obviously didn't know how to advertise.
So this is not just a few hours of Saturday work. Before Saturday, before the invitation is sent out to Bangaloreans to come and paint the flyover, there are a bunch of Ugly Indian volunteers who spend many hours in removing the posters from the pillars, cleaning the pillars and then spending a lot of time in carefully painting the entire pillar!!!
That's not just a lot of work, that's a LOT of time and money too!
I wanted to know how this is done, so early Saturday morning, I visited Nagavara flyover. I didn't have time to participate, but this is what I found:
The pillars were already painted orange and white.
But a closer examination revealed...
The white lines were not paint. It's white tape.
And sure enough, a little away there were people applying more tape.
On the other side of the road, some pillars were labelled with chalk.
And if you are an early bird, you get to choose which colours everyone has to paint on the triangles.
By 11:30am, most of the pillars had been painted by volunteers wearing yellow aprons...
...and as I suspected, they had painted onto the tape as well, so the nice white outlines you saw earlier, were no longer visible. There was some paint that had dripped down too. The tape is removed eventually, leaving orange lines separating all the triangles. The bottom of the pillars, where some paint dripped down, would also be re-painted with the orange paint and I'm quite sure some volunteers would return to put finishing touches to the triangles where the paint of one triangle slightly overlapped the paint of another triangle.
These are some of the other UFO paintings. This photo was sent to many of us by email, from the Ugly Indian group.
Splendid effort!
The takeaway from this is not just about using your free time to volunteer to make this world a more beautiful place, but the takeaway is also that when you volunteer, make sure you put in enough of effort to do it correctly.
There are far too many volunteering groups in India, which do not care about going into detail. This holds especially true for corporate employee volunteering, where the objective is just to hold a tiny event for a few hours, not so that society is benefited, but so that the company is benefited because they got a chance to amuse their employees and de-stress them for some time.
When you volunteer, do it because you want to improve things. Not because you want to make a name for yourself or impress someone.
More on volunteering
...this UFO (Under The Flyover) project made me wonder how they painted it so neatly.
- Who draws those white lines so accurately?
- How do they prevent the paint from trickling down?
- Is it really a few hours of work?
![]() |
| Screenshot from Facebook |
Turns out that before the orange paint was applied, the flyover pillars were covered with posters from people who obviously didn't know how to advertise.
![]() |
| Screenshot from Facebook |
So this is not just a few hours of Saturday work. Before Saturday, before the invitation is sent out to Bangaloreans to come and paint the flyover, there are a bunch of Ugly Indian volunteers who spend many hours in removing the posters from the pillars, cleaning the pillars and then spending a lot of time in carefully painting the entire pillar!!!
That's not just a lot of work, that's a LOT of time and money too!
I wanted to know how this is done, so early Saturday morning, I visited Nagavara flyover. I didn't have time to participate, but this is what I found:
The pillars were already painted orange and white.
But a closer examination revealed...
The white lines were not paint. It's white tape.
And sure enough, a little away there were people applying more tape.
On the other side of the road, some pillars were labelled with chalk.
And if you are an early bird, you get to choose which colours everyone has to paint on the triangles.
By 11:30am, most of the pillars had been painted by volunteers wearing yellow aprons...
...and as I suspected, they had painted onto the tape as well, so the nice white outlines you saw earlier, were no longer visible. There was some paint that had dripped down too. The tape is removed eventually, leaving orange lines separating all the triangles. The bottom of the pillars, where some paint dripped down, would also be re-painted with the orange paint and I'm quite sure some volunteers would return to put finishing touches to the triangles where the paint of one triangle slightly overlapped the paint of another triangle.
These are some of the other UFO paintings. This photo was sent to many of us by email, from the Ugly Indian group.
Splendid effort!
The takeaway from this is not just about using your free time to volunteer to make this world a more beautiful place, but the takeaway is also that when you volunteer, make sure you put in enough of effort to do it correctly.
There are far too many volunteering groups in India, which do not care about going into detail. This holds especially true for corporate employee volunteering, where the objective is just to hold a tiny event for a few hours, not so that society is benefited, but so that the company is benefited because they got a chance to amuse their employees and de-stress them for some time.
When you volunteer, do it because you want to improve things. Not because you want to make a name for yourself or impress someone.
More on volunteering
- Build a good reputation for volunteers
- How to start volunteering or a volunteering team
- How good is your volunteering team? The Nav test.
- Blood donation. What went right?
- Donating to every cause is impractical
Subscribe to:
Posts (Atom)

































