|
|
|
|
|
GoDaddy.com TechFest 2009
Starting in 2008, every year GoDaddy.com holds the TechFest event at the F1 Race Factory here in Phoenix. The event is for all the folks in the hosting department and features employee lead courses, food, and go cart racing.
When I was there, I met up with the GoDaddy.com girl Candice Michelle:

|
| |
chroot and mounting
Recently I've ran into problems when I am using a 32-bit OS and dealing with 64-bit files. In my case, I have a layout like this:
/tmp/64-bit-files-here
The main system I have is 32-bit and I untar a 64-bit root file system to the folder /tmp/64-bit-files-here. At this point, I want to chroot and run a shell script but I'm unable to. Since I would be chroot-ed, the binaries that would be used are coming from /tmp/64-bit-files-here/bin and /tmp/64-bit-files-here/sbin and they are 64-bit and won't run.
Symlinks won't work because as soon as you chroot, that path is invalid. I had to read some man pages and do some searching, but I found a solution. The way I got around this is by using mount. I made the appropriate folders in my 64-bit file system folder:
mkdir /tmp/64-bit-files-here/tmp-root
mkdir /tmp/64-bit-files-here/tmp-root/bin
mkdir /tmp/64-bit-files-here/tmp-root/etc
mkdir /tmp/64-bit-files-here/tmp-root/lib
mkdir /tmp/64-bit-files-here/tmp-root/sbin
#create other directories here
cp /tmp/MyShellScript.sh /tmp/64-bit-files-here/tmp-root
Then I used mount to provide a link-like functionality. I mount the 32-bit executable directories but I load the 64-bit file directories such as etc. Note the --bind argument:
mount --bind /bin /tmp/64-bit-files-here/tmp-root/bin
mount --bind /tmp/64-bit-files-here/etc /tmp/64-bit-files-here/tmp-root/etc
mount --bind /lib /tmp/64-bit-files-here/tmp-root/lib
mount --bind /sbin /tmp/64-bit-files-here/tmp-root/sbin
#mount other directories here
chroot /tmp/64-bit-files-here/tmp-root /MyShellScript.sh
When you do chroot, you'll have access to run the 32-bit executables but modify your 64-bit file system. This specific example might only be useful if you're doing imaging but the chroot / mount example should be useful for any kind of scripting.
|
| |
Cron Quick Reference
On Linux you can schedule tasks using cron. To open up cron just run:
crontab -e
Something useful to paste into your crontab is this line:
#mh hd dm my dw command
Like most Linux configuration files, lines starting with # are comments. This comment shown above is helpful to show you the field order that a cron line is broken down into. Each cron is on it's own line and it's parameters are space separated. Here's an explanation of the abbreviations found in the comment:
mh - minute of the hour (0-59)
hd - hour of the day (0-23)
dm - day of the month (1-31)
my - month of the year (0-12)
dw - day of the week (0-6, with 0 being Sunday)
command - command to run
For each value you can put an asterisk if you always want it to run. For example, if you put an asterisk for mh, the command will run every minute (see example 1).
You can also add a list by comma seperating values (see example 2).
Alternatively, you can use a range by using the hypen (see example 3 and 4).
The last way you can provide a value is using a step value. For example, if you want to run a command every other day, you can basically provide the dm field with */2 (see example 5).
Here are a few examples that should help show how crontab entries work:
#mh hd dm my dw command
#example 1: executes once per minute (every day)
* * * * * echo "This is a test"
#example 2: executes every day at 10am, noon, and 2pm
0 10,12,14 * * * echo "This is a test"
#example 3: executes every day on every hour between at 10am and 2pm
0 10-14 * * * echo "This is a test"
#example 4: executes Monday thru Friday at 2pm
0 14 * * 1-5 echo "This is a test"
#example 5: executes every other day at 2pm
0 14 */2 * * echo "This is a test"
#example 6: executes every day at 2pm and logs
0 14 * * * echo "This is a test" >> /var/log/results.log 2>&1
Note that in example 6 above, I redirect standard output and standard error into a log file. This is the best way to grab the output from your cron.
This information was put together using these articles:
http://troy.jdmz.net/cron/
http://www.unixgeeks.org/security/newbie/unix/cron-1.html
|
| |
grep -P is not supported on Ubuntu
On Ubuntu, the man page of grep states that the flag -P or --perl-regexp can be used to use a PERL regular expression. But when the command is run with either flags you get the following error message:
grep: The -P option is not supported
This has officially been a bug for a while; it appears to be a hot issue. Some folks have even suggested "fixing it" by removing -P from the man page. More details can be found here:
https://bugs.launchpad.net/ubuntu/+source/grep/+bug/15051
Regardless of all that chatter, I found a pretty easy solution that works. You can copy the grep executables and libraries from a machine that has a Red Hat distribution installed. Just SCP the files over and you're ready to go:
mv /bin/grep /bin/grep.bak
scp user@192.168.1.1:/bin/grep /bin/grep
scp user@192.168.1.1:/lib/libpcre.so.0.0.1 /lib
cd /lib
ln -s libpcre.so.0.0.1 libpcre.so.0
|
| |
Identifying the Linux Distro running
Sample C program I wrote based on this article:
http://www.novell.com/coolsolutions/feature/11251.html
#include <stdio.h>
typedef enum{
DISTRO_UNKNOWN=-1,
DISTRO_SUSE=0,
DISTRO_REDHAT,
DISTRO_FEDORA,
DISTRO_SLACKWARE,
DISTRO_DEBIAN,
DISTRO_MANDRAKE,
DISTRO_YELLOW_DOG,
DISTRO_SUN_JDS,
DISTRO_SOLARIS_SPARC,
DISTRO_GENTOO,
DISTRO_UNITEDLINUX,
DISTRO_UBUNTU
} LinuxDistro;
char FileExists(char* strFile)
{
FILE* f = fopen(strFile,"r");
if(f){
fclose(f);
return(1);
}
return(0);
}
LinuxDistro IdentifyLinuxDistro(void)
{
if(FileExists("/etc/SUSE-release"))
return(DISTRO_SUSE);
if(FileExists("/etc/redhat-release"))
return(DISTRO_REDHAT);
if(FileExists("/etc/redhat_version"))
return(DISTRO_REDHAT);
if(FileExists("/etc/fedora-release"))
return(DISTRO_FEDORA);
if(FileExists("/etc/slackware-release"))
return(DISTRO_SLACKWARE);
if(FileExists("/etc/slackware-version"))
return(DISTRO_SLACKWARE);
if(FileExists("/etc/debian_release"))
return(DISTRO_DEBIAN);
if(FileExists("/etc/debian_version"))
return(DISTRO_DEBIAN);
if(FileExists("/etc/mandrake-release"))
return(DISTRO_MANDRAKE);
if(FileExists("/etc/yellowdog-release"))
return(DISTRO_YELLOW_DOG);
if(FileExists("/etc/sun-release"))
return(DISTRO_SUN_JDS);
if(FileExists("/etc/release"))
return(DISTRO_SOLARIS_SPARC);
if(FileExists("/etc/gentoo-release"))
return(DISTRO_GENTOO);
if(FileExists("/etc/UnitedLinux-release"))
return(DISTRO_UNITEDLINUX);
if(FileExists("/etc/lsb-release"))
return(DISTRO_UBUNTU);
return(DISTRO_UNKNOWN);
}
int main(int argc,char** argv)
{
LinuxDistro distro = IdentifyLinuxDistro();
switch(distro){
case DISTRO_SUSE: printf("SUSE"); break;
case DISTRO_REDHAT: printf("Redhat"); break;
case DISTRO_FEDORA: printf("Fedora"); break;
case DISTRO_SLACKWARE: printf("Slackware"); break;
case DISTRO_DEBIAN: printf("Debian"); break;
case DISTRO_MANDRAKE: printf("Mandrake"); break;
case DISTRO_YELLOW_DOG: printf("Yellow dog"); break;
case DISTRO_SUN_JDS: printf("Sun JDS"); break;
case DISTRO_SOLARIS_SPARC: printf("Solaris/Sparc"); break;
case DISTRO_GENTOO: printf("Gentoo"); break;
case DISTRO_UNITEDLINUX: printf("UnitedLinux"); break;
case DISTRO_UBUNTU: printf("Ubuntu"); break;
default: printf("Unknown"); break;
}
return(0);
}
|
| |
My Ubuntu Experience
I use Linux a lot at work and I'm starting to like it. When it comes to development I still prefer Windows but Linux has definitely gotten much better than when I had first started using it. I'm mostly familiar with Red Hat distributions like Fedora and CentOS so I wasn't sure what to expect when I came across Ubuntu.
http://www.ubuntu.com/
I haven't tried Linux on my home machine since Mandrake 9 came out so I burned a Live CD for 8.04 LTS (desktop) and tried it out on my Shuttle SG33G5. Ubuntu booted up quickly and I honestly liked the look and feel. Even though it appears to be targeted at newbies, there is a huge amount of support online for it. Using it for a few minutes was enough to convince me to jump in and configure my machine for dual booting.
On my home computer I primarily use Microsoft Windows Vista Ultimate Edition. I do a lot of Windows programming at home and really enjoy it. One of the great features built into Vista is the ability to resize your partitions on the fly (before this, you'd have to use a 3rd party tool). After doing some searching, I resized my partition using these notes:
http://www.bleepingcomputer.com/tutorials/tutorial133.html
Basically you just go into Disk Management in the Computer Management administrative tool. When there you can right click the partition and choose "Resize" to resize the partition as needed. I shrank the disk to allow to reserve approximately 50 gigabytes for Ubuntu.
When I install Linux, I like to use the ext3 filesystem with these partitions:
/boot - 100 MB
swap - 2048 MB
/ - rest of available space
The first thing I noticed about Ubuntu was that vi was screwed up; it wasn't behaving properly. For example, I would go into insert mode and using the arrow keys would start typing letters. After a little research, I found a fix:
sudo apt-get remove vim-tiny
sudo apt-get install vim
After getting vi squared away, I needed to fix the nVidia drivers. Don't discount the Shuttle SG33G5 because of it's small size; even though it only has a 250 watt power supply, you can comfortably shove in a GeForce 9800GT 16x PCI-Express card.
I found a great article on the Ubuntu forums about getting the driver installed and working.
http://ubuntuforums.org/showthread.php?t=862203
After getting the nVidia driver up and running, I figured I would check out Mono. I've been extremely interested in learning more about it, especially given how much C# and .NET development I do. There is a lot of great documentation available on the homepage:
http://monodevelop.com/
You can just open a console window and grab these packages:
sudo apt-get install monodevelop
sudo apt-get install mono-gmcs
sudo apt-get install automake
Once you do, you can open up MonoDevelop. It has a very similar look and feel to Visual Studio. I made a few quick and dirty C# applications and I am impressed!
|
| |
Extracting an RPM without installing it
rpm2cpio MyRpmFile.rpm | cpio -idmv
|
| |
Unix / Linux User Management Quick Reference
On Linux you can add a user with the useradd utility:
/usr/sbin/useradd -p 'hash' -G GroupNameHere UserNameHere
If the user already exists, edit the group or password hash using usermod:
/usr/sbin/usermod -p 'hash' -G GroupNameHere UserNameHere
If you need to grant sudo privilege to only the user, you can add them using:
/usr/sbin/visudo
The actual password hashes are stored in /etc/shadow file. This file is only readable by root. It is delimited by colons and has the following information:
1) Login name
2) Encrypted password
3) Date when password was last changed (days since Jan 1, 1970)
4) Minimum number of days required between password changes
5) Maximum number of days the password is valid
6) Number of days before password expires that user is warned about password change
7) Number of days after password expires that account is disabled
8) An absolute date when the login may no longer be used (days since Jan 1, 1970)
If the password field is surrounded with *, the user account is locked.
If the password field is surrounded with !, the user's password has expired.
The /etc/passwd file also contains user account information. This file is also delimited by colons and has the following information:
1) Login Name
2) Password (x means encrypted password is stored in /etc/shadow)
3) User ID
4) Group ID (stored in /etc/group file)
5) Comment
6) Home directory
7) Command/shell (e.g. /bin/bash)
The /etc/group file contains user group information. Like the other two files it is colon delimited. This file contains the following information:
1) Group Name
2) Password (usually blank, not commonly used)
3) Group ID
4) Comma seperated list of user logins that comprise this group
This information was put together using man pages and these articles:
http://www.cyberciti.biz/faq/understanding-etcshadow-file/
http://www.cyberciti.biz/faq/understanding-etcpasswd-file-format/
http://www.cyberciti.biz/faq/understanding-etcgroup-file/
|
| |
Executing a program at startup on Windows
Run and RunOnce registry keys cause programs to run each time that a user logs on. The data value for a key is a command line. Register programs to run by adding entries of the form description-string=commandline. You can write multiple entries under a key. If more than one program is registered under any particular key, the order in which those programs run is indeterminate.
The Windows registry includes the following four keys:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
By default, the value of a RunOnce key is deleted before the command line is run. You can prefix a RunOnce value name with an exclamation point (!) to defer deletion of the value until after the command runs. Without the exclamation point prefix, if the RunOnce operation fails the associated program will not be asked to run the next time you start the computer.
By default, these keys are ignored when the computer is started in Safe Mode. The value name of RunOnce keys can be prefixed with an asterisk (*) to force the program to run even in Safe mode.
For more information, check out these articles:
http://support.microsoft.com/kb/179365
http://msdn.microsoft.com/en-us/library/aa376977(VS.85).aspx
|
| |
Cox Communications - Star Code Guide
The following list may be useful if you have Cox Digital Telephone for your telephone service. There are a lot of features which are activated by star codes.
*57 - Have Cox trace the last phone call received. Costs approx. $2.75 per use. Call law enforcement after the trace to report the call.
*60 - Selective call rejection. You are presented with a menu where you can block numbers from calling you.
*64 - Selective call acceptance. You are presented with a menu where you can input numbers you only want to receive (all others are blocked).
*61 - Set up different "ring-tones" for different phone numbers.
*67 - Will make your number anonymous on a per-call basis (e.g. you must dial this each time before dialing out). If not per call, turn off by dialing *82.
*69 - gives the number of the last caller (only if caller is not anonymous). Costs approx. $0.75 per use.
*71 - Three-way calling.
*72 - Call forwarding. Forward to your cell phone, etc. Effective until you dial *73 from the phone you activated call forwarding from.
*77 - Block all anonymous calls. Effective until un-blocked using *87.
|
| |
VBScript - Quick and dirty file downloader
usage: cscript script.vbs "http://www.myurl.com/myfile.jpg", "C:\output\myfile.jpg"
Set oArgs = WScript.Arguments
If oArgs.Count <> 2 Then
Wscript.Echo "Error: Wrong number of arguments!"
Wscript.Quit 1
End If
strDownloadURL = oArgs(0)
strSaveAsURL = oArgs(1)
Set oHttp = CreateObject("Microsoft.XMLHTTP")
oHttp.open "GET", strDownloadURL, false
oHttp.send()
If oHttp.status <> 200 Then
WScript.Echo "Failed getting the file: " & strDownloadURL & vbCrLf & "Error: " & oHttp.statusText
WScript.Quit 2
End If
SaveFileToDisk strSaveAsURL, oHttp.ResponseBody
Function SaveFileToDisk(strFileName, oData)
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Dim oStream: Set oStream = CreateObject("ADODB.Stream")
oStream.Type = adTypeBinary
oStream.Open
oStream.Write oData
oStream.SaveToFile strFileName, adSaveCreateOverWrite
Set oStream = Nothing
End Function
|
| |
Waiting for msiexec.exe to complete
If you just invoke an MSI package from the command line, msiexec will execute asynchronously. To get around this you can use start /wait from your batch file. This will create the process and wait for it to exit. Type start /wait before the command line you'd normally pass to msiexec.exe like so:
start /wait msiexec.exe /i MyMSI.msi /l*v MyMSI.log
The batch file would be blocked until msiexec.exe finishes. Programmatically this is the same as invoking msiexec.exe with CreateProcess and waiting for the process to return from WaitForSingleObject with no timeout.
|
| |
Bob Parson's 16 Rules For Success
Professionally, I work as a Software Engineer at GoDaddy.com. The crazy Super Bowl ads and fun company culture are what attracted me to work there. The owner of GoDaddy.com, Bob Parsons, has a list of "16 rules for success in business or life in general" which I thought were worth sharing.
1. Get and stay out of your comfort zone.
2. Never give up.
3. When you are ready to quit, you're closer than you think.
4. Accept the worst possible outcome.
5. Focus on what you want to have happen.
6. Take things a day at a time.
7. Always be moving forward.
8. Be quick to decide.
9. Measure everything of significance.
10. Anything that is not managed will deteriorate.
11. Pay attention to your competitors, but pay more attention to what you're doing.
12. Never let anybody push you around.
13. Never expect life to be fair.
14. Solve your own problems.
15. Don't take yourself too seriously.
16. There's always a reason to smile.
Bob's motto is "We're not here for a long time, we're here for a good time". He has a video blog which has a lot of great material worth checking out. He also reads every comment and responds to a lot of them.
http://www.bobparsons.tv/
|
| |
Shell Execute with output in C#
Using the System.Diagnostics.Process class you can get a stream to read the output of the application you are executing. For example, you could execute "dir" to list get the directory contents of the working directory specified as a string.
Here's a basic class I wrote that allows you to get the standard output:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace BrianClifton{
class WindowsHelper{
public static Exception ShellExecute(string in_WorkingDirectory,string in_FileName,string in_Args,out string out_StdOut)
{
Process p = new System.Diagnostics.Process();
p.StartInfo.WorkingDirectory = in_WorkingDirectory;
p.StartInfo.FileName = in_FileName;
p.StartInfo.Verb = "open";
p.StartInfo.Arguments = in_Args;
//required to capture standard output
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
p.WaitForExit();
//read the command line output
try{
StreamReader sr = p.StandardOutput;
out_StdOut = sr.ReadToEnd();
return(null);
}catch(Exception ex){
out_StdOut = "";
return(ex);
}
}
}
}
|
| |
ToString for C++ base types
#include <sstream>
template <class T>
inline std::string ToString(const T& t)
{
std::stringstream ss;
ss << t;
return(ss.str());
}
|
| |
Creating or moving a MySQL database
Unlike my experience with SQL Server, you cannot reliably move a MySQL database by moving the binary files in the MySQL directory. Instead, you should use the mysqldump utility.
Open a command line window to the MySQL bin directory and make sure both mysql and mysqldump binaries are both present. On Linux this location is likely /usr/local/mysql/bin and on Windows this is most likely C:\Program Files\MySQL\MySQL Server 5.0\
Dump the database using a command like this:
./mysqldump --user=user --password=pw database_name_here > db.sql
Then connect using the MySQL command line client and create the database:
./mysql --user=user --password=pw
create database new_database_name
use new_database_name
source db.sql
|
| |
Logging in automatically in Windows
On every media center PC I've used, most of the usage didn't involve a keyboard. With Windows Media Center Edition 2005 I mostly used the MCE remote control and with my new Windows Vista machine I use a touch screen.
One obstacle for getting the perfect setup on your media center is the logging in process. On Windows XP or Vista you'll have to click a Windows XP user icon (or enter a username) and enter the password (if applicable) to log in. I want to have a password to protect shared content but I don't want to have to actually log in or click the frog Windows XP user icon next to the name "Brian". I want my user account to automatically log in and have it run a startup script, open up commonly used programs, etc. There is a fix available for Windows XP / Windows Vista.
Use the Start Menu -> Run to pull up the run box (or on Vista, just pull up the start menu and click on the "start search") and type in "control userpasswords2". Hit enter and you will be presented with a "User Accounts" dialog. Simply uncheck the "Users must enter a user name and password to use this computer" box. When you click "Apply" or "OK", the dialog will prompt you with the credentials you want to use to automatically log in. Enter the user you would like to be automatically logged in and you're ready to go.
|
| |
SCOPE_IDENTITY
In SQL Server, there are three ways to get the identity of the row you had just inserted: IDENT_CURRENT(), @@IDENTITY, and SCOPE_IDENTITY().
IDENT_CURRENT() is not limited by scope and session; it is limited to a table. For example, you can use IDENT_CURRENT('TableName') to get the last identity generated for table 'TableName'.
SCOPE_IDENTITY() and @@IDENTITY will return last identity values generated in any table in the current session. However, only SCOPE_IDENTITY() returns values inserted within your current scope (the scope of the SQL you just executed). @@IDENTITY is dangerous to use in my opinion because even though it is limited to session, it doesn't take into account identities that could have been made by triggers. SCOPE_IDENTITY() is always safe to use after making your insert to get exactly the identity you need.
For more information, check out the official MSDN documentation:
http://msdn.microsoft.com/en-us/library/aa259185(SQL.80).aspx
|
| |
Randomizing your selection in SQL Server
Sometimes you might want to randomize your dataset. In the SQL driven MP3 player I worked on, I wrote a stored procedure to handle putting together a playlist for the user (since all the song data is already in the database). There are probably a lot of other good uses for random selections and the code sample below works great.
In your select clause you can add an ORDER BY statement and use NEWID().
SELECT * FROM
TableName
ORDER BY NEWID()
|
| |
Date formatting using MySQL
By default MySQL stores its dates in 'YYYY-MM-DD HH:MM:SS' format. When you have to integrate with .NET, it's nice to get the date in a format which is readable by DateTime.Parse().
In your SQL query, you can format the date by using the date_format function.
SELECT date_format(YourDateHere, '%a %D %b %Y') FROM TableName;
Here are some example formatting strings and examples of their output (replace the formatting in the red part of the query above).
| Example | Format String | | 1/28/2008 | '%c/%e/%Y' | | 01/28/2008 | '%m/%d/%Y' | | 1/28/2008 12:30 | '%c/%e/%Y %H:%i' | | 01/28/2008 12:30 | '%m/%d/%Y %H:%i' | | 1/28/2008 12:30:59 | '%c/%e/%Y %T' | | 01/28/2008 12:30:59 | '%m/%d/%Y %T' |
|
| |
C++ String Stream
After using C++ for many years, I found myself still using the printf family of C functions for formatting. When I started my new job this last March, I noticed the other folks are big on using string streams. I've been trying to ween myself off sprintf and wanted to share some very simple examples.
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc,char** argv)
{
ostringstream buffer;
buffer << "Testing " << 1 << 2 << 3 << endl;
cout << buffer.str();
return(0);
}
This code will output:Testing 123
That code isn't too bad. If that's all there was too it, I wouldn't mind using the string streams. However, advanced formatting is not so easy. But of course you can always use defines to help.
Let's say that we want a program to display today's date in MM/DD/YYYY format. Using C, this is extremely trivial.
int main(int argc,char** argv)
{
time_t time1 = time(0);
struct tm* time2 = localtime(&time1);
printf("Today's date is: %02d/%02d/%04d\n",time2->tm_mon,time2->tm_mday,(1900+time2->tm_year));
return(0);
}
However, I don't think the code very elegant using string streams.
#include <iostream>
#include <sstream>
#include <time.h>
#include <iomanip>
using namespace std;
#define FormatInt(number,spaces) setw(spaces) << setfill('0') << int(number)
int main(int argc,char** argv)
{
time_t time1 = time(0);
struct tm* time2 = localtime(&time1);
ostringstream buffer;
buffer << "Today's date is: " << FormatInt(time2->tm_mon,2) << "/" << FormatInt(time2->tm_mday,2) << "/" << FormatInt(1900+time2->tm_year,4) << endl;
cout << buffer.str();
return(0);
}
If there is a better way to do this I'd love to hear about it. For now, I'll use string streams at work and continue using sprintf in code at home.
|
| |
Bugzilla Install Guide for Windows
In December I installed Bugzilla on my file server to help track bugs and enhancements for all of my personal projects. Bugzilla is a pleasure to use, especially after years of using Mercury Quality Center at work. In my opinion it doesn't have any bloat and is easy to modify to your needs. The developers did a great job.
http://www.bugzilla.org/
Installing the program was not easy. But after an hour or so of beating my head on the desk I found an excellent Windows install guide by Byron Jones. The install guide gives an overview of locating and configuring Bugzilla, Perl, Apache, and MySQL.
http://www.bugzilla.org/docs/win32install.html
|
| |
Bjarne Stroustrup: The creator of the C++ programming language
Last August I stumbled upon the personal website of Bjarne Stroustrup, the creator of the C++ programming language. I am a pretty big fan of his and it was great to read the articles and FAQ on his personal web site.
http://www.research.att.com/~bs/
I was surprised to see his email listed so I wrote him a quick message:
Hi Bjarne,
I found your homepage randomly today and wanted to let you know how
much I enjoy the C++ language. I own your book (which I've read
through many times) , "The C++ Programming Language", and I really
enjoy programming in C++.
This might be an odd request, but would I be able to get an
autographed photo of you? I would proudly display this in my office
everyday, especially if it had a silly line like "Brian, you'll never
be as good as me at C++ but thanks for buying my book - Bjarne".
I'm a 26 year old software engineer and my entire career was founded
on the knowledge I gained by becoming an expert at C++. If you were
up for that, it would mean a lot. If not, that's ok too. Thanks for
everything
Cheers
Brian
About a week later I was checking the mail and noticed a large envelope from TAMU
(click for larger).
"To Brian Clifton, All the best with C++"
|
| |
SQLite Quick Reference
The homepage for SQLite claims that it is the most deployed widely SQL database in the world. I don't know if that is true but SQLite is a powerful light-weight SQL database.
http://sqlite.org/
I discovered this library while I was talking to some folks on IRC (#C++ on EFNET). I was working on the Jukebox program at the time and needed a "default" database. The first version of the program I wrote required the MSDE to be installed which was way too heavy / hard to configure for end users. I dug into SQLite (version 3.x) and one immediate downside was that I had to get the source code and hack around before I could use it. Even though the documentation wasn't great I was pleased with the result.
Setup
Start off by just downloading the DLL. On the download page grab the version for Windows that says "This is a DLL of the SQLite library without the TCL bindings". After downloading the zip, you'll notice there is only a .DLL and a .DEF file. You'll need a header and a .lib file in order to compile against the DLL.
Open up the Visual Studio command prompt and navigate to the folder you unzipped the DLL/DEF to. You can then run this command:
lib /machine:i386 /def:sqlite3.def
This will generate the .lib and .exp for the DLL. What I did to find the header is download the source code for the library itself. I grabbed the "sqlite3.h" header file from the source code that was grouped as "individual source files". Once you grab the header just add the link to the .lib file in your compiler and you're ready.
Opening and closing the database
#include "sqlite3.h"
sqlite3* db;
if(sqlite3_open("my_database.db",&db)){
printf("Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
//handle error here...
}
When you're done using the database, close it using:
sqlite3_close(db);
Executing Non-Queries
std::string sql = "UPDATE Song SET AlbumID = NULL;";
if(sqlite3_exec(db,sql.c_str(),0,0,0)){
printf("Failed to update rows: %s\n",sqlite3_errmsg(db));
//handle error here...
}
Executing Queries (SELECTing data)
Executing SELECT queries in SQLite is pretty horrible in my opinion. You execute it the same way as you do a non-query, except you will need to use the callback parameter.
//SQLite DB, SQL query, callback function name, data to pass to callback, error msg
sqlite3_exec(db,sql_query_here,callback_here,NULL,0);
//this callback gets called for EVERY ROW returned by the query
int SampleCallback(void* data,int argc,char **argv,char** ColName)
{
//returned record is in argv
//column names are in ColName
//data is a pointer which you can pass in the exec statement
int SongID = atoi(argv[0]);
std::string SongName = std::string(argv[1]);
return(0);
}
Other notes
In my experience SQLite is pretty slow. If you're after performance you'll definitely want to choose MS SQL Server, Oracle, or MySQL. SQLite only allows for one "connection" so to speak. You'll want to wrap a mutex around your DB calls or else you'll get unexpected behavior.
If you're a big MS SQL Server programmer like I am, you are probably used to getting the ID of the entry you just inserted. This is possible in SQLite. For example, if I insert a Song into my database and I want to get the identity of the Song entry that was just inserted... in SQL Server (in a stored procedure) you would use SCOPE_IDENTITY(). I had to ask around and then I found the SQLite function:
int myRowId = sqlite3_last_insert_rowid(db);
|
| |
CVS Quick Reference
Useful Commands
Initial check-out
cvs co -r branch_name module_name
Protip: the -r specifies that you want to checkout from a tag/branch.
Branching
cvs tag -b branch_name
Get latest
cvs up -Pd
Protip: the P prunes empty directories and the d will cause directories to be created as needed.
Commit / check-in changes
cvs commit
Protip: Always do a cvs up before you commit. Running cvs up will automatically merge if needed. Then you can view the merge (if one occured) and manually disposition it.
Adding /removing a file
cvs add file.txt
cvs delete file.txt
Protip: After adding or deleting a file you must commit the change in order for it to be visible to other users.
Checking differences against a branch
cvs diff -r branch_name
Protip: In my opinion, using Tortoise CVS with WinMerge is much easier than the command line cvs diff tool.
Merging a branch
cvs up -j branch_name -Pd
Protip: the j is what actually causes the merge to happen (merges changes made between working directory and the branch you provide).
When all else fails
cvs --help-options
cvs up --help-options
cvs co --help-options
cvs diff --help-options
What the letters mean when doing a CVS update
U - updated successfully
A - added but not yet committed (need to run a cvs commit)
R - removed but not yet committed (need to run a cvs commit)
M - modified in your working directory: the file in the repository was changed and your working directory file was older than the last time CVS checked it OR the repository had changes which the system could safely merge
C - there was a conflict between the repository copy and your copy which requires human intervention
? - the file is in your working directory but not the repository and CVS doesn't know what to do with it
The format of CVSROOT
The CVSROOT is basically your connection string to the source repository. These are your credentials to login to CVS. The CVSROOT is in this format:
:pserver:username@computer_name:repository
Downloads
Tortoise CVS - a Windows shell integration interface for CVS
http://www.tortoisecvs.org/
WinMerge - a diff utility. Integrates with Tortoise
http://winmerge.org/
|
| |
|
|