Saturday, April 13, 2013

Muting the MacOS startup sound

Auto-mute your Mac's speakers each time you turn it off

Got this great tip from lifehacker. It actually turns off all sounds (mute) each time you shut down. Not the exact thing I was looking for (I only wanted to disable the one startup sound), but we've used it for a year or so on our Mac and love it.

Create a file named /Library/Scripts/mute.sh
#!/bin/bash
osascript -e 'set volume with output muted'
Then run these commands:
sudo chmod u+x /Library/Scripts/mute.sh
sudo defaults write com.apple.loginwindow LogoutHook /Library/Scripts/mute.sh

Monday, March 4, 2013

Patching VMware Tools in Fedora 18

Patching VMware Tools so HGFS (host-guest file system) will run in Fedora 18

There are several bugs in the current release of VMware Tools (VMwareTools-9.2.2-893683). Below are some patches and scripts to fix those. You can download these files from my GitHub repo:

https://github.com/ebdevrepo/bin

People have also had good results with this patch: http://communities.vmware.com/message/2130250

(1) Kernel include file bug

There is currently a bug in the vmware-install.pl script. It will fail to find header files. To fix that, run this script [download] and then re-run vmware-install.pl:

#!/bin/bash
KVER=`uname -r`
cp /usr/src/kernels/$KVER/include/generated/uapi/linux/version.h /lib/modules/$KVER/build/include/linux/

(2) VMCI driver bug

There is a second bug in the vmware-install.pl script. It will fail to compile the vmci driver. See these posts:

https://patchwork.kernel.org/patch/1963371/
http://communities.vmware.com/message/2182440#2182440

You know you are encountering this bug if you see these compile errors when running vmware-install.pl:


make[1]: Entering directory `/usr/src/kernels/3.8.1-201.fc18.x86_64'
  CC [M]  /tmp/modconfig-grfWex/vmci-only/linux/driver.o
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:127:4: error: implicit declaration of function ‘__devexit_p’ [-Werror=implicit-function-declaration]
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:127:4: error: initializer element is not constant
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:127:4: error: (near initialization for ‘vmci_driver.remove’)
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:1754:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vmci_probe_device’
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:1982:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vmci_remove_device’
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:119:12: warning: ‘vmci_probe_device’ used but never defined [enabled by default]
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:121:13: warning: ‘vmci_remove_device’ used but never defined [enabled by default]
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:2063:1: warning: ‘vmci_interrupt’ defined but not used [-Wunused-function]
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:2137:1: warning: ‘vmci_interrupt_bm’ defined but not used [-Wunused-function]
/tmp/modconfig-grfWex/vmci-only/linux/driver.c:1717:1: warning: ‘vmci_enable_msix’ defined but not used [-Wunused-function]
cc1: some warnings being treated as errors
make[2]: *** [/tmp/modconfig-grfWex/vmci-only/linux/driver.o] Error 1
make[1]: *** [_module_/tmp/modconfig-grfWex/vmci-only] Error 2
make[1]: Leaving directory `/usr/src/kernels/3.8.1-201.fc18.x86_64'
make: *** [vmci.ko] Error 2
make: Leaving directory `/tmp/modconfig-grfWex/vmci-only'

The communication service is used in addition to the standard communication 
between the guest and the host.  The rest of the software provided by VMware 
Tools is designed to work independently of this feature.
If you wish to have the VMCI feature, you can install the driver by running 
vmware-config-tools.pl again after making sure that gcc, binutils, make and the
kernel sources for your running kernel are installed on your machine. These 
packages are available on your distribution's installation CD.


To work around this, first install the patch utility:

  sudo yum install patch

Create this vmware9.k3.8rc4.patch file [download] in your vmware-tools-distrib directory:

--- compat_mm.h.orig 2013-03-04 01:36:39.184925478 -0800
+++ compat_mm.h 2013-03-04 01:40:37.793728289 -0800
@@ -91,8 +91,9 @@
 /*
  * In 2.4.10, vmtruncate was changed from returning void to returning int.
+ * In 3.8.0,  vmtruncate was removed
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 10)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
 #define compat_vmtruncate(inode, size)                                        \
 ({                                                                            \
    int result = 0;                                                            \
@@ -100,7 +101,16 @@
    result;                                                                    \
 })
 #else
-#define compat_vmtruncate(inode, size) vmtruncate(inode, size)
+#define compat_vmtruncate(inode, size)                                        \
+({                                                                            \
+   result = inode_newsize_ok(inode, size);                                    \
+   if (!result)                                                               \
+   {                                                                          \
+      truncate_setsize(inode, size);                                          \
+   }                                                                          \
+   result;                                                                    \
+})
+
 #endif

Then run this script from your vmware-tools-distrib directory [download]. If it asks you if this is a reverse patch, select no (type the letter 'n').

#!/bin/bash
pushd lib/modules/source
if [[ ! -f vmci.tar.orig ]]
then
  cp vmci.tar vmci.tar.orig
fi
rm -rf vmci-only
tar xf vmci.tar
pushd vmci-only
patch -p1 < ../../../../vmware9.k3.8rc4.patch
popd
tar cf vmci.tar vmci-only
rm -rf vmci-only
popd


(3) VMHGFS bug


You know you are encountering this bug if you see these compile errors when running vmware-install.pl:


  CC [M]  /tmp/modconfig-kxIA61/vmhgfs-only/inode.o
/tmp/modconfig-kxIA61/vmhgfs-only/inode.c: In function ‘HgfsTruncatePages’:
/tmp/modconfig-kxIA61/vmhgfs-only/inode.c:888:4: error: implicit declaration of function ‘vmtruncate’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make[2]: *** [/tmp/modconfig-kxIA61/vmhgfs-only/inode.o] Error 1
make[1]: *** [_module_/tmp/modconfig-kxIA61/vmhgfs-only] Error 2
make[1]: Leaving directory `/usr/src/kernels/3.8.1-201.fc18.x86_64'
make: *** [vmhgfs.ko] Error 2
make: Leaving directory `/tmp/modconfig-kxIA61/vmhgfs-only'

The filesystem driver (vmhgfs module) is used only for the shared folder 
feature. The rest of the software provided by VMware Tools is designed to work 
independently of this feature.

If you wish to have the shared folders feature, you can install the driver by 
running vmware-config-tools.pl again after making sure that gcc, binutils, make
and the kernel sources for your running kernel are installed on your machine. 
These packages are available on your distribution's installation CD.


Create this vmware9.compat_mm.patch file [download] in your vmware-tools-distrib directory:

--- ./compat_mm.h 2013-03-04 01:36:39.184925478 -0800
+++ ./compat_mm.h 2013-03-04 01:40:37.793728289 -0800

@@ -91,8 +91,9 @@
 /*
  * In 2.4.10, vmtruncate was changed from returning void to returning int.
+ * In 3.8.0,  vmtruncate was removed
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 10)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
 #define compat_vmtruncate(inode, size)                                        \
 ({                                                                            \
    int result = 0;                                                            \
@@ -100,7 +101,16 @@
    result;                                                                    \
 })
 #else
-#define compat_vmtruncate(inode, size) vmtruncate(inode, size)
+#define compat_vmtruncate(inode, size)                                        \
+({                                                                            \
+   result = inode_newsize_ok(inode, size);                                    \
+   if (!result)                                                               \
+   {                                                                          \
+      truncate_setsize(inode, size);                                          \
+   }                                                                          \
+   result;                                                                    \
+})
+
 #endif

Then run this script [download] from your vmware-tools-distrib directory:

#!/bin/bash


pushd lib/modules/source

if [[ ! -f vmhgfs.tar.orig ]]
then
  cp vmhgfs.tar vmhgfs.tar.orig
fi
rm -rf vmhgfs-only
tar xf vmhgfs.tar
pushd vmhgfs-only/shared
patch -p1 < ../../../../../vmware9.compat_mm.patch
popd
tar cf vmhgfs.tar vmhgfs-only
rm -rf vmhgfs-only
popd

** NOTE ** Any time there is a kernel update you will need to re-install VMware Tools to get hgfs working again (the ability for the VM to access files from the host OS).

Tuesday, February 26, 2013

Configuring the Fedora window manager

Pick a different window manager


There are lots of window managers out there. Right now, Gnome is having some trouble running in a VM because VMWare's 3D acceleration does not work with it. Pick a lighterweight one like Cinnamon.

  sudo yum install cinnamon

Reboot. When you are entering your password to log in, use the services dropdown to change to Cinnamon (or whatever other window manager you selected).

Smaller title bars

The default title bar on Fedora windows is too tall. It wastes a lot of screen real estate. After trying several of the suggestions out on the 'net, I found that this one works for me (Fedora 18 with Cinnamon window manager).

http://mikeyshelpdesk.blogspot.com/2011/04/gnome-3-massive-title-bar.html

* Find your metacity theme files. They should be in /usr/share/themes/Adwaita/metacity-1
* Find each instance of "title_vertical_pad" and change it to zero

*** NOTE: You'll need to make this change each time the .xml files are updated.

Adding Ruby on Rails to the development environment

Ruby on Rails

Once you have your basic development environment up and running, you may want to add Ruby on Rails to it. Follow these steps.

Tools to install

$ sudo yum install ruby
$ sudo yum install ruby-devel
$ sudo yum install sqlite-devel
$ sudo gem install rails
$ sudo gem install therubyracer

Install MySQL

This page is far more informative and covers many other use cases and linux variants: http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch34_:_Basic_MySQL_Configuration

But, if you want a super-quick startup, here goes...

$ sudo yum install mysql
$ sudo yum install mysql-server
$ sudo yum install mysql-devel
$ sudo chkconfig mysqld on
$ sudo service mysqld start    # or reboot
$ mysqladmin -u root password "the password"
$ mysql --user=root --password="the password"
mysql> create database dev;
mysql> grant all privileges on dev.* to devuser@"localhost" identified by 'a password';
mysql> quit;
$ mysql --user=devuser --password="a password"
mysql> use dev;

Pro Tip: If you are in a VM this would be a great time to take a snapshot.

Verify Rails is Working

$ cd ~
$ mkdir test
$ cd test
$ rails new testapp
$ cd testapp
$ vi Gemfile
<add the line, "gem 'therubyracer'" somewhere near the top of the file>
$ rails server

Start a web browser and navigate to: http://localhost:3000/ You should see the test app page.

Verify Rails can communicate with MySQL

$ cd ~
$ mkdir test
$ cd test
$ rails new testdb -d mysql
$ cd testdb
$ vi Gemfile
<add the line, "gem 'therubyracer'" somewhere near the top of the file>
$ vi config/database.yml
<find the "development" section and change your user, password, and database name>
$ rails server

Start a web browser and navigate to: http://localhost:3000/ You should see the test app page.

Create a Rails "Hello World" app

$ cd ~
$ mkdir test
$ cd test
$ rails new testdb -d mysql
$ cd testdb
$ vi Gemfile
<add the line, "gem 'therubyracer'" somewhere near the top of the file>
$ vi config/database.yml
<find the "development" section and change your user, password, and database name>
$ vi config/routes.rb
<add the line, "  resources :users">
# Read more about routes here: http://guides.rubyonrails.org/routing.html
$ rails generate conroller users
$ rails generate model users
$ vi app/views/users/index.html.erb
<Put a "hello world" page in it>
$ rails server

Start a web browser and navigate to: http://localhost:3000/users You should see the "hello world" page.


Monday, February 25, 2013

Acronyms

Acronyms that I run into from time to time

There is a set of acronyms that I run into often enough to need to know what they are, but not often enough to actually remember what they are. I'm hoping that by writing them down it will help me remember them.

ACID - Atomicity, Consistency, Isolation, Durability. The properties that make up a reliable database updating mechanism. http://en.wikipedia.org/wiki/ACID

AJAX - Asynchronous JavaScript and XML. This one is slippery. XML is not required; JSON is usually used. The requests do not need to be asynchronous. Essentially, this is a way of building UIs wherein the UI is responsible for polling information from the server at the UI's desired update rate. This is all on the UI; there is no server control over the rate. http://en.wikipedia.org/wiki/Ajax_(programming)

CRUD - Create, Read, Update, Delete. These are the basic functions needed to implement persistent storage. http://en.wikipedia.org/wiki/Create,_read,_update_and_delete

DRY - Don't Repeat Yourself http://en.wikipedia.org/wiki/Don%27t_repeat_yourself

RESTful - Representational State Transfer. The implementation has at least six distinct, defining constraints. But, in a nutshell, a client shall be able to exist independently of a specific server (there may be caching and intermediates in the middle). The client shall be able to make requests of the server at any time. The server shall store no information about the client.
http://en.wikipedia.org/wiki/RESTful

RAII - Resource Acquisition is Initialization. The practice of wrapping the acquisition of a resource in a management object that is guaranteed to release it. http://en.wikipedia.org/wiki/RAII


Technical Books I Own

Technical books I have read or am reading

JavaScript: The Good Parts

I have not started reading this yet. It was given to me by a friend who works at a company that uses JavaScript heavily. He assures me that the core of the language is actually very solid.


Programming Pearls, Second Edition

Only a little way into this. I would read it faster, but there are *so* many programming exercises to stop and puzzle out first.


Concrete Mathematics: A Foundation for Computer Science



Purely Functional Data Structures

This wasn't quite what I thought it would be. I was expecting to be led through a discussion of new data structures that really only apply to functional programming. Instead, it shows mostly well-known data structures (lists, trees, etc.) and talks about the performance differences between functional and imperative programming.


Haskell: The Craft of Functional Programming

Yuck! What a horrible book. Maybe, if you have never touched a computer in your life, you could start with this book. But, even then, I think you would throw it out the window after the first chapter. The author takes 10 pages to say what, well, really doesn't need to be said. For instance, what is a function? Does the author really need 10 pages to describe what a function is? It takes about two sentences to describe what a function is. However, this author stretches it over 10 pages of dumbed-down analogies and fluff. Can you imagine how confused a reader can become after reading through 10 pages? I have been doing software development for 30 years and *I* was getting confused by this guy. Not because functions are hard (they aren't), but because he is a horrible writer.


Learn You a Haskell for Great Good!

This is the book to read if you want to learn Haskell. Get this book.


Effective C++, Third Edition

Over the years I have read this book cover-to-cover probably 4 times. And, I'm reading it again. It really is a good book. Get it. Read it. Learn it. Read it again every few years.


The Algorithm Design Manual


Introduction to Algorithms, Third Edition




Using 'perf' to profile your program in Fedora

Installing perf

If perf is not already on your system, run this command:

  $ sudo yum install perf

On my system that installed: perf-3.7.9-101.fc17.x86_64

Running your application to collect data

One of the nice things about perf is that you don't need to compile your executable in any special way. You can run perf no matter how you built your executable (as far as I know). To profile your application, do this:

  $ perf stat ./bigint_test


   Performance counter stats for './bigint_test':

        11461.887097 task-clock                #    1.015 CPUs utilized        
                 155 context-switches              #    0.014 K/sec                
                   0 cpu-migrations                  #    0.000 K/sec                
                 335 page-faults                      #    0.029 K/sec                
     <not supported> cycles
                   0 stalled-cycles-frontend      #    0.00% frontend cycles idle  
     <not supported> stalled-cycles-backend
     <not supported> instructions
     <not supported> branches
     <not supported> branch-misses

        11.290034097 seconds time elapsed

I'm running Fedora in a VM and have not enabled all of the performance pass-through options. That means I don't get to see some of the performance profile data. My roommate is working on computing very large prime numbers and this data is hugely valuable for him. For me, I don't use this output from perf much. I prefer to run perf in this way...

  $ perf record ./bigint_test
  [ perf record: Woken up 5 times to write data ]
  [ perf record: Captured and wrote 1.351 MB perf.data (~59033 samples) ]

In my VM I'm doing my development in a directory mounted from the host OS. This allows me to share files easily between the host OS and the guest OS (Fedora). One drawback to this is that the file ownership of that mounted directory is not me. perf complains if I try to examine the perf.data file when I don't own it, so I move the file to my home directory and then examine it.

  $ mv perf.data ~
  $ cd
  $ perf report
   61.98%  bigint_test  bigint_test        [.] BigInt::validate(char const*, int) const
   10.18%  bigint_test  bigint_test        [.] BigInt::import(int)
    3.92%  bigint_test  bigint_test        [.] BigInt::isDivisibleBy(int) const
    2.86%  bigint_test  bigint_test        [.] BigInt::compare(BigInt const&) const
    2.49%  bigint_test  bigint_test        [.] BigInt::BigInt(int)
    2.28%  bigint_test  bigint_test        [.] BigInt::extendBuffer(unsigned int)
    2.00%  bigint_test  bigint_test        [.] BigInt::length() const
    1.60%  bigint_test  bigint_test        [.] testDivisibility(unsigned int)
    1.58%  bigint_test  bigint_test        [.] BigInt::~BigInt()
    1.49%  bigint_test  libc-2.15.so       [.] __memcpy_ssse3_back
    1.38%  bigint_test  bigint_test        [.] BigInt::subtractStrings(char*, char const*)
    1.26%  bigint_test  bigint_test        [.] BigInt::addStrings(char*, char const*)
    0.84%  bigint_test  bigint_test        [.] BigInt::isZero() const
    0.70%  bigint_test  bigint_test        [.] BigInt::operator=(BigInt const&)
    [...]

Now I have some really useful information. BigInt::validate() is taking up 61.98% of the time. This is a debug-only routine that is only used in this test executable and does not appear in my development executables. I can ignore this. But, I see that BigInt::import() is taking a lot of CPU time. I should go look at how I can optimize that routine. And, each time I try an optimization I should re-run the performance metrics. Things that I think will be optimizations often make no difference or actually cost me time.

Analyzing the data