Wednesday, October 28, 2009

Auto-map Network drives

The command lines for connecting, disconnecting and mapping the network drive are trivia once you know them.

net use X: \\192.168.10.17\www
maps X: to 192.168.10.17\www

net use /DELETE X:
removes the mapped network drive

Now I can just run this batch file .. easy!
net use /DELETE X:
net use X: \\192.168.10.17\www

Monday, October 26, 2009

Samba Cheatmap

I created this mindmap for Samba Configuration using freemind- hence cheatmap. I am always baffled with what to do next. I find this very useful to move ahead while configuring.
First you create a group for accessing samba directory, add samba users and change their primary group to newly created group. This group is used to access the samba folder with directory mask and create mask set. Any user with this group will have read and write access to the folder. You have to open some ports for samba - i directly make change in iptables file. Command is recommended. In fedora, you also have to make changes in SELinux. Finally after making changes in the configuration file, start/restart the samba service.
You  may also download the pdf or freemind file from github.


Tuesday, October 20, 2009

Looping in bash for multiple operations

Just learned that bash also supports looping that can be used to do the multiple operations on the files in a given folder.

for old in *.png; do  convert $old `basename $old .png`.eps;done

converts all the png files in a given folder to postscript file.

If there are i1.png, i2.png and i3.png then expansion of above loop will be
convert i1.png e1.eps
convert i2.png e2.eps
convert i3.png e3.eps

Note there is space between $old and .png

Similarly renaming *.png to mt_*.png
for old in *.png; do cp $old my_.`basename $old .png`;done

Saturday, October 10, 2009

Update: PHP eval is powerful indeed

I came up with a solution though not very elegant one to the options dependent looping, by using eval() function once more. Took time to came up with the solution, especially it's not very easy to debug, except for outputting the code to the screen before executing eval().
"Person A", "PROJECT"=>1, "COUNTRY"=>1, "HOURS"=>40),
  array("NAME"=>"Person A", "PROJECT"=>1, "COUNTRY"=>1, "HOURS"=>30),
  array("NAME"=>"Person A", "PROJECT"=>1, "COUNTRY"=>2, "HOURS"=>70),
  array("NAME"=>"Person A", "PROJECT"=>2, "COUNTRY"=>2, "HOURS"=>10),
  array("NAME"=>"Person A", "PROJECT"=>3, "COUNTRY"=>1, "HOURS"=>50),
  array("NAME"=>"Person B", "PROJECT"=>1, "COUNTRY"=>2, "HOURS"=>40),
  array("NAME"=>"Person B", "PROJECT"=>1, "COUNTRY"=>2, "HOURS"=>10),
  array("NAME"=>"Person B", "PROJECT"=>2, "COUNTRY"=>2, "HOURS"=>50),
  );
$expecteddata1 = array(
  array("NAME"=>"Person A", "HOURS"=>200),
  array("NAME"=>"Person B", "HOURS"=>100),
);
$expecteddata2 = array(
  array("NAME"=>"Person A", "PROJECT"=>1, "HOURS"=>140),
  array("NAME"=>"Person A", "PROJECT"=>2, "HOURS"=>10),
  array("NAME"=>"Person A", "PROJECT"=>3, "HOURS"=>50),
  array("NAME"=>"Person B", "PROJECT"=>1, "HOURS"=>50),
  array("NAME"=>"Person B", "PROJECT"=>2, "HOURS"=>50),
);

function groupData($input, $byOptions) {
  $str = "";
  foreach($byOptions as $option) {
    $str .= '[$row['.$option.']]';
  }
  $data = array();
  foreach($input as $rowid=>$row) {
    eval("@\$data".$str."['hours'] += ".$row['HOURS'].";");
  }
  
  $newdata = array();
  
  $str = ""; 
  $count = 0;
  foreach($byOptions as $option) {
    $str .= '"'.$option.'"=>"$id'.$count.'",';
    $count ++;
  }
  $str='array('.$str.'"HOURS"=>"$hours")';

  $count = 0;
  $forstr = 'foreach($data as $id'.($count).'=>$arr'.($count).') {';
  foreach($byOptions as $option) {
    if($count >= (sizeof($byOptions)-1))  {
      $forstr .= '$hours=$arr'.$count.'["hours"];';
      break;
    }
    $forstr .= 'foreach($arr'.$count.' as $id'.($count+1).'=>$arr'.($count+1).') {';
    $count++;
  }
  $forstr .= '$newdata[]='.$str.';';
  $count = 0;
  foreach($byOptions as $option) {
    if($count >= (sizeof($byOptions)-1))  {
      break;
    }
    $forstr .= '}';
    $count ++;
  }
  $forstr .= '}';
  
  //print $forstr;
  eval("$forstr");
  return $newdata;
}

$output1 = groupData($data, array("NAME"));
print ($expecteddata1 == $output1)?"Same":"Different Objects";

$output2 = groupData($data, array("NAME", "PROJECT"));
print ($expecteddata2== $output2)?"Same":"Different Objects";  
?>

Friday, October 09, 2009

PHP eval is powerful indeed!

I have this array probem.
A set of data
$data = array(
  array("NAME"=>"Person A", "PROJECT"=>1, "COUNTRY"=>1, "HOURS"=>40),
  array("NAME"=>"Person A", "PROJECT"=>1, "COUNTRY"=>1, "HOURS"=>30),
  array("NAME"=>"Person A", "PROJECT"=>1, "COUNTRY"=>2, "HOURS"=>70),
  array("NAME"=>"Person A", "PROJECT"=>2, "COUNTRY"=>2, "HOURS"=>10),
  array("NAME"=>"Person A", "PROJECT"=>3, "COUNTRY"=>1, "HOURS"=>50),
  array("NAME"=>"Person B", "PROJECT"=>1, "COUNTRY"=>2, "HOURS"=>40),
  array("NAME"=>"Person B", "PROJECT"=>1, "COUNTRY"=>2, "HOURS"=>10),
  array("NAME"=>"Person B", "PROJECT"=>2, "COUNTRY"=>2, "HOURS"=>50),
  );
which i want in this format
$expecteddata1 = array(
  array("NAME"=>"Person A", "HOURS"=>200),
  array("NAME"=>"Person B", "HOURS"=>100),
);
and also this,
$expecteddata2 = array(
  array("NAME"=>"Person A", "PROJECT"=>1, "HOURS"=>140),
  array("NAME"=>"Person A", "PROJECT"=>2, "HOURS"=>10),
  array("NAME"=>"Person A", "PROJECT"=>3, "HOURS"=>50),
  array("NAME"=>"Person B", "PROJECT"=>1, "HOURS"=>50),
  array("NAME"=>"Person B", "PROJECT"=>2, "HOURS"=>50),
);
The expected data need grouping among multiple numbers of options. Note the Total.

It took some time to come with the solution after working a bit with the powerful eval() function.

It's much easy to do the looping and grouping as follows
for($data as $rowid=>$row) {
  $newdata[$row["NAME"]] += $row["HOURS]; //gives the data required for $expecteddata1
  $newdata[$row["NAME"]][$row["PROJECT]] += $row["HOURS]; //gives the data required for $expecteddata2
}
which can be made to work for any number of options with
for first case $byOptions = array("NAME");
and for second case $byOptions = array("NAME", "PROJECT");
$str = "";
  foreach($byOptions as $option) {
    $str .= '[$row['.$option.']]';
  }
  $data = array();
  foreach($input as $rowid=>$row) {
    eval("@\$data".$str."['hours'] += ".$row['HOURS'].";");
  }

and next loop through $newdata and generate the expecteddata. This part of code needs to be refactored. If any of you can come up with good solution to remove the options dependent looping, it would be great. [update: I came up with solution in next post that eliminates the options dependent looping using eval]

function groupData($input, $byOptions) {
  $str = "";
  foreach($byOptions as $option) {
    $str .= '[$row['.$option.']]';
  }
  $data = array();
  foreach($input as $rowid=>$row) {
    eval("@\$data".$str."['hours'] += ".$row['HOURS'].";");
  }
  
  $newdata = array();
  foreach($data as $id=>$arr) {
    if(isset($arr['hours'])) {
      $newdata[] = array($byOptions[0]=>$id, 'HOURS'=>$arr['hours']);
    } else {
      foreach($arr as $id1=>$arr1) {
        if(isset($arr1['hours'])) {
          $newdata[] = array($byOptions[0]=>$id, $byOptions[1]=>$id1, 'HOURS'=>$arr1['hours']);      
        } else {
          foreach($arr1 as $id2=>$arr2) {
            $newdata[] = array($byOptions[0]=>$id, $byOptions[1]=>$id1, $byOptions[2]=>$id2, 'HOURS'=>$arr2['hours']);     
          }
        }
      }
    }
  }  
  return $newdata;
}

Test the function. It should work.
$output1 = groupData($data, array("NAME"));
print ($expecteddata1 == $output1)?"Same":"Different Objects";

$output2 = groupData($data, array("NAME", "PROJECT"));
print ($expecteddata2== $output2)?"Same":"Different Objects";  

Wednesday, October 07, 2009

Split big image to two in Latex with ease

If you have one large image that doesn't fit in your page, then you open some photo editor, split the image into two and put those images in two images. Nice! Now your text gets edited (added, removed, updated) and the split images do not seem to fit as they were. You again open up image editor and do the process, hoping that no more edits are required.

You are in luck if you are latex user, you can just change some numbers and split the image on the fly without having to tinker with image editors.

(0,1500)                (600,1500)
 ---------------------
|                               |
|                               |
|                               |
 ---------------------
(0,900)                  (600,900)
 ---------------------
|                               |
|                               |
|                               |
 ---------------------
(0,0)                     (600,0)

First display the first half image with the coordinates(0,900) and (600,1500).
\begin{figure}[h]
 \centering
  \fbox{
   \scalebox{0.5}{\includegraphics*[viewport=0 900 600 1500]{large_image.png}}
  }
\end{figure}
Now display the second part of the image.
\begin{figure}[h]
 \centering
  \fbox{
   \scalebox{0.5}{\includegraphics*[viewport=0 0 600 900]{large_image.png}}
  }
 \caption{Caption only here}
 \label{Label only here}
\end{figure}

Tuesday, December 25, 2007

xdebug: Function Tracing using Profiling

Every now and then you would be looking at the codes of others. Thanks to open-source, I have had many such instances and had really hard time following the code. Take mediawiki, drupal, owl, dotproject just to name a few. Xdebug allows you to log all function calls, including parameters and return values to a file in different formats. The output log format can be customized. Like I may need the function calls only, just to trace the order of function calls.

The xdebug.org has a page on function trace.

It's not a good practice to write the configuration parameters in php.ini or xdebug.ini file (you may also do that, but you don't want to trace other applications). These ini files set global configuration. It's no wonder that xdebug makes everything slow. So be careful. If you are wondering about xdebug.ini, it's a separate config file for xdebug extension. rather than writing to php.ini file. See my previous post on building xdebug.

.htaccess comes to aid, when you don't want to write either to your source code or .ini file.

Create .htaccess file in the directory of the application you want to trace.
php_value xdebug.auto_trace 1
php_value xdebug.trace_format 0
php_value xdebug.trace_output_dir /var/www/trace
php_value xdebug.trace_options 1
See the meaning of above configuration from here. There are other parameters if you need to see the parameters passed and the return values.

Make sure that the directory /var/www/trace is writable by your web-server.

Load the php script in your browser. You will see a new file has been created at the output location.

The file size can get very huge. Like in the case of mediawiki code, loading index.php creates a trace file of size 3M.

TRACE START [2007-12-25 05:24:23]
0.0018 68304 -> {main}() /var/www/testwiki/index.php:0
0.0037 87332 -> require_once(/var/www/testwiki/includes/WebStart.php) /var/www/testwiki/index.php:38
0.0039 87460 -> str_replace() /var/www/testwiki/includes/WebStart.php:10
0.0041 87800 -> ini_get() /var/www/testwiki/includes/WebStart.php:19
0.0043 87800 -> microtime() /var/www/testwiki/includes/WebStart.php:51
0.0045 87860 -> function_exists() /var/www/testwiki/includes/WebStart.php:53
0.0047 87880 -> getrusage() /var/www/testwiki/includes/WebStart.php:54
0.0050 89420 -> ini_set() /var/www/testwiki/includes/WebStart.php:59
0.0052 89420 -> define() /var/www/testwiki/includes/WebStart.php:66
0.0057 91252 -> require_once(/var/www/testwiki/StartProfiler.php) /var/www/testwiki/includes/WebStart.php:69
0.0059 91252 -> dirname() /var/www/testwiki/StartProfiler.php:3
0.0071 101736 -> require_once(/var/www/testwiki/includes/ProfilerStub.php)
.....
.....
2.1464 8033332 -> strlen() /var/www/testwiki/includes/OutputHandler.php:14
2.1466 8033332 -> wfDoContentLength() /var/www/testwiki/includes/OutputHandler.php:14
2.1467 8033332 -> headers_sent() /var/www/testwiki/includes/OutputHandler.php:96
2.1930 74168
TRACE END [2007-12-25 05:24:37]

This file is 27028 lines long. Huge, isn't it? The file looks simple, nonetheless long. It should give a good idea of what functions are being called.

I just found another convenient way of function tracing by using the profiling feature.

Xdebug's built-in profiler allows you to find bottlenecks in your script and visualize those with an external tool such as KCacheGrind or WinCacheGrind.

While viewing the profiler output, I realized that it's an excellent way of viewing the tracing function calls.

To enable profiler, replace the content of .htaccess file with the following lines
php_value xdebug.profiler_output_dir /var/www/trace
php_value xdebug.profiler_enable 1
Load the php script from browser. You will see the file cachegrind.out file being created. There are two such files in my case. I wonder why.

Now download WinCacheGrind that beautifies the above created file in a very convenient manner.

Load the cachegrind.out file in WinCacheGrind. You will notice that the left pane displays the function calls, and included file in a same sequence as that of function trace output file above.


You may browse through the tree of function calls and probably understand the code flow in much less time. You will also see that the php internal function are labelled as php::functionname so you can just concentrate on user functions. Happy hacking.