Friday, November 28, 2008

Kentucky, 2006

"The 2006 law organizing the state Office of Homeland Security lists its initial duty as "stressing the dependence on Almighty God as being vital to the security of the Commonwealth."

Specifically, Homeland Security is ordered to publicize God's benevolent protection in its reports, and it must post a plaque at the entrance to the state Emergency Operations Center with an 88-word statement that begins, "The safety and security of the Commonwealth cannot be achieved apart from reliance upon Almighty God.""

http://www.kentucky.com/210/story/608229.html

This is 2006. No kidding. Welcome to Jesusland!

It's Thanksgiving, not a Halloween! Why am I scared?

"In fact, in commercial and academic turkey-breeding programs, adult male turkeys, called toms, can reach 50 pounds at the tender age of five months, said John Anderson, a longtime turkey breeder at Ohio State University.

"We get 50 pounders at 20 weeks, but that's at the top edge of our normal distribution," Anderson said. "We've got some adult male-line birds that went over 80 pounds.""

http://blog.wired.com/wiredscience/2008/11/turkeytech.html

Organic Avocados

"I told my wife to stop this organic food malarkey,'' said Jeremy, a beleaguered hedge-fund manager, another man who fell for an extremely beautiful yet extravagant woman.

"She went ballistic. Organic Hass avocados cost £1.75 each and she wanted me to buy six of them! In the end, I just peeled off the labels that said they were certified organic and put them on ordinary avocados – she didn't notice the difference. I did the same with bananas…"

http://www.telegraph.co.uk/finance/financetopics/recession/3527803/Recession-When-the-money-goes-so-does-the-toxic-wife.html

Tuesday, November 25, 2008

US automakers vs. Honda

"You need to give people the freedom to spend and the freedom to make mistakes," says Takeo Fukui, Honda's 61-year-old president. "If management oversight is too strong, then it's difficult to innovate."

"There's not a company on earth that better understands the culture of engineering."

Very interesting article in Forbes about engineering-dominated Honda vs. marketing-dominated automakers in the US.

This is generally true beyond car manufacturing - at most US companies marketing and finance rules, technology and manufacturing get outsourced.

Even in hi-tech, there are fewer and fewer engineers at on near the top - the trend started during the .COM boom when the geekish software companies got "integrated" into society as a legitimate make money fast industry, and it never really ended.

How many VPs did you see that are "proud of the smart people who are making all these great products", but are decidedly (and pointedly) not one of them?

We're now reaping the "rewards" of the culture where it's not smart to be smart...

http://www.forbes.com/forbes/2006/0904/112.html

Monday, November 24, 2008

You know why the economy tanked? It's because we're not religulous enough!

Under Faux News aegis, Wall Street Journal opinion page is reaching the whole new level of ridiculous...

http://online.wsj.com/article/SB122714101083742715.html

Friday, November 21, 2008

Wednesday, November 19, 2008

RIP PC Magazine

http://www.paidcontent.org/entry/419-ziff-davis-to-close-print-pcmag-focus-on-online-still-looking-for-optio/

The last time I held it in my hands was some time in the late nineties, but it is an end of an era...

Alienation

"According to presidential historian Davis Logsdon of the University of Minnesota, some Americans might find it "alienating" to have a president who speaks English as if it were his first language."

http://www.huffingtonpost.com/andy-borowitz/obamas-use-of-complete-se_b_144642.html

Taking a private jet to beg for a bailout

http://abcnews.go.com/Blotter/WallStreet/story?id=6285739&page=1

Note also the salaries of these "leaders" in the article above.

Incidentally, none of these excesses existed before Reagan's tax cuts, and they do not exist today in Europe where taxes on super-high incomes are accordingly high.

Tuesday, November 18, 2008

Mekong Delta

In 1968 US has carried an Operation Speedy Express in the heavily populated Mekong river delta. The orders were to achieve the high body count at all costs.

That was achieved: 10899 enemy casualties were reported, with only 267 American losses.

The problem? Only 748 weapons recovered. Much of the rest were civilians.

http://www.thenation.com/doc/20081201/turse

Maybe in Ohio, but not in America!

"If it wasn't for Bush we would be out of street waving white flags
waiting for the salvation army trucks to bring us our daily meal.

I fear that with a liberal at helm, the only direction we'll be
steering for is Deep, Deadly Depression.

I am contemplating moving to Canada or somewhere in Europe. Push comes
to shove, I may even move to Mexico or Hawaii, as long as it's a
different country
and I can get away with the depression that is
inevitable if a the government liberalizes everything."

http://finance.google.com/group/google.finance.358464/browse_thread/thread/5e9d0da4985a76c3?pli=1

Check out the reaction of Canadians down in the thread: "As a Canadian, i have to say, please don't come here. we don't need people like you!"

Exchange web services 2007

A few snippets from my weekly status database that show how to interact with EWS 2007.

First, you need to generate EWS 2007 proxy. In Visual Studio it is relatively easy: Project->Add service reference, enter the address of your exchange web server, for example, https://mail.microsoft.com/EWS/Exchange.asmx (you won't be able to use this one because it is obviously secured). Hit Go, then name the namespace and hit OK.

One problem with EWS 2007 is that it unfortunately requires user credentials - cleartext (they are sent using HTTPS, so the wire security is not a problem, but the user has to enter the password/user name, or the software needs to CryptProtectData the credentials and store them. Windows auth is not available.

See here for a snippet of code that stores the password SECURELY: http://1-800-magic.blogspot.com/2008/11/encrypting-data-in-net.html. Make sure you're running under real user account (not LocalService, and definitely not NetworkSerivce), otherwise anybody will be able to decrypt the password.

Once the proxy has been generated, and put in the namespace, and the namespace has been included in the file with "using" directive, we can start coding.

First, we need to bind to the service. Binding is required for all examples below:
const string EXCHANGE_URL = @"https://mail.mydomain.com/EWS/Exchange.asmx";
ExchangeServiceBinding binding = new ExchangeServiceBinding();
binding.Credentials = new NetworkCredential(User, Password, Domain);
binding.Url = EXCHANGE_URL;
Looking up a subfolder of inbox:
DistinguishedFolderIdType inbox = new DistinguishedFolderIdType();
inbox.Id = DistinguishedFolderIdNameType.inbox;
BaseFolderIdType[] parentFolder = new BaseFolderIdType[1];
parentFolder[0] = inbox;

FindFolderType folderRequest = new FindFolderType();
folderRequest.FolderShape = new FolderResponseShapeType();
folderRequest.FolderShape.BaseShape = DefaultShapeNamesType.AllProperties;
folderRequest.Traversal = FolderQueryTraversalType.Shallow;
folderRequest.ParentFolderIds = parentFolder;

FindFolderResponseType folderResponse = binding.FindFolder(folderRequest);
foreach (ResponseMessageType responseMessage in folderResponse.ResponseMessages.Items)
{
FindFolderResponseMessageType findFolderResponseMessage =
responseMessage as FindFolderResponseMessageType;
if (findFolderResponseMessage.ResponseClass == ResponseClassType.Success)
{
BaseFolderType[] folders = findFolderResponseMessage.RootFolder.Folders;
foreach (BaseFolderType folder in folders)
{
if (folder.DisplayName.Equals(folderWeAreLookingFor))
{
...do stuff
}
}
}
}
Here's how to get all email (we're only getting the ids of messages, the contents needs to be queried using a different request, covered later:

DistinguishedFolderIdType inbox = new DistinguishedFolderIdType();
inbox.Id = DistinguishedFolderIdNameType.inbox;
BaseFolderIdType[] parentFolder = new BaseFolderIdType[1];
parentFolder[0] = inbox;

FindItemType listRequest = new FindItemType();
listRequest.ItemShape = new ItemResponseShapeType();
listRequest.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
listRequest.Traversal = ItemQueryTraversalType.Shallow;
listRequest.ParentFolderIds = parentFolder;

FindItemResponseType listResponse = binding.FindItem(listRequest);

List items = new List();

foreach (ResponseMessageType responseMessage in listResponse.ResponseMessages.Items)
{
FindItemResponseMessageType findItemResponseMessage =
responseMessage as FindItemResponseMessageType;
if (findItemResponseMessage.ResponseClass == ResponseClassType.Success)
{
ArrayOfRealItemsType realItems =
findItemResponseMessage.RootFolder.Item as ArrayOfRealItemsType;
if (realItems != null && realItems.Items != null)
{
foreach (ItemType item in realItems.Items)
{
if (item is MessageType)
{
MessageType message = item as MessageType;
items.Add(message.ItemId);
}
}
}
}
}
Now, suppose we accumulated all message ids that we want to get in the items list, (we presume that items.Count() > 0). We will now get all the messages as follows:
GetItemType getRequest = new GetItemType();
getRequest.ItemShape = new ItemResponseShapeType();
getRequest.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
getRequest.ItemIds = items.ToArray();

SnippetsDataContext snippets = new SnippetsDataContext(Database);

GetItemResponseType getResponse = binding.GetItem(getRequest);
foreach (ResponseMessageType responseMessage in getResponse.ResponseMessages.Items)
{
ItemInfoResponseMessageType getItemResponseMessage =
responseMessage as ItemInfoResponseMessageType;
if (getItemResponseMessage.ResponseClass == ResponseClassType.Success)
{
ArrayOfRealItemsType realItems =
getItemResponseMessage.Items as ArrayOfRealItemsType;
if (realItems != null && realItems.Items != null)
{
foreach (ItemType item in realItems.Items)
{
if (item is MessageType)
{
MessageType message = item as MessageType;
// Message now contains everything, except for attachments.
...
}
}
}
}
}
Suppose we want to move a message to a different folder. We need to find folder's id (see above for how to enumerate folders). If we do have this id, and the id of the message we're trying to move:

MoveItemType moveRequest = new MoveItemType();
moveRequest.ToFolderId = new TargetFolderIdType();
moveRequest.ToFolderId.Item = targetFolder;
moveRequest.ItemIds = new BaseItemIdType[1];
moveRequest.ItemIds[0] = messageId;
MoveItemResponseType moveResponse = binding.MoveItem(moveRequest);
Ok, enough moving stuff around. Let's send something!

ExchangeServiceBinding binding = new ExchangeServiceBinding();
binding.Credentials = new NetworkCredential(User, Password, Domain);
binding.Url = EXCHANGE_URL;

DistinguishedFolderIdType folder = new DistinguishedFolderIdType();
folder.Id = DistinguishedFolderIdNameType.sentitems;

TargetFolderIdType targetFolder = new TargetFolderIdType();
targetFolder.Item = folder;

CreateItemType createItem = new CreateItemType();
createItem.MessageDisposition = MessageDispositionType.SendAndSaveCopy;
createItem.MessageDispositionSpecified = true;
createItem.SavedItemFolderId = targetFolder;

MessageType message = new MessageType();

EmailAddressType recipient = new EmailAddressType();
recipient.EmailAddress = "email@domain.com";

message.ToRecipients = new EmailAddressType[1];
message.ToRecipients[0] = recipient;
message.Subject = "Hello, World!";
message.Sensitivity = SensitivityChoicesType.Normal;

message.Body = new BodyType();
message.Body.BodyType1 = BodyTypeType.Text;
message.Body.Value = "This is my first automated email!";

createItem.Items = new NonEmptyArrayOfAllItemsType();
createItem.Items.Items = new MessageType[1];
createItem.Items.Items[0] = message;
binding.CreateItem(createItem);
Many messages can be acted upon (moved, sent, deleted) by one command - all it takes is putting multiple messages or ids in Items.Items array.

Dealing with the web service is A LOT of code - even with the help of the proxy. Comare this to the Office interop, where most of the above tasks take 10-15 lines of code. http://1-800-magic.blogspot.com/2008/11/fun-with-outlook-and-net.html

More on EWS 2007 here: http://msdn.microsoft.com/en-us/library/bb418726.aspx

Monday, November 17, 2008

However stupid our Republican VP candidate might look...

...things are far, far worse in Russia. A couple of juicy quotes...

""Medvedev will serve his term and may be re-elected for another," says Edward Lozansky, a former dissident. "It is none of the British press's business anyway. Go and teach your British wives to cook cabbage soup.""
...

"Until last week, Svetlana, a young mother of two, held decidedly middle-class ambitions. An executive at a construction company, she was hoping to save enough to send her children to school in Britain and buy a new flat in an upmarket part of Moscow. But then, without warning, she was made redundant along with about 70 colleagues. She received no severance pay and was instead forced to sign a letter saying she had voluntarily resigned.
"They said that if I didn't sign then I could look forward to burying my own children," Svetlana says. "What kind of country do we live in? I thought we were close to becoming a civilised nation, but I've been forced to realise that that is an illusion.""

http://www.telegraph.co.uk/news/worldnews/europe/russia/3469652/Russias-crumbling-economy-provides-stiffest-test-yet-for-autocratic-leader.html

Sorting in C# with delegates

A delegate can be handy to avoid having to implement an IComparer class.

Suppose you need to sort an array of dates in descending order...

DateTime[] availableDates = allMailDates.ToArray();
Array.Sort(availableDates, delegate(DateTime d1, DateTime d2) {
return Math.Sign(d2.ToBinary() - d1.ToBinary());
});

Saturday, November 15, 2008

First encounter with T-SQL

I am building a little app for my team that collects weekly status emails and publishes it on a web site. Since I've worked on far lower level stuff most of my career (I only wrote the code that actually has UI at Google), it's fun and educating.

Using ASP.NET is quite fun actually - Microsoft REALLY nailed developer experience on this one. The API is logical, concise, well structured, and a pure joy to use. I started with having no clue whatsoever, and had a fully-functioning web app running in around two hours, and this included reading a book.

This story is about T-SQL, however. There came time where I wanted a stored procedure. On my website, there is an adminitrative user who can make changes in a database, and everybody else can do unlimited reading (anybody can see everybody's status mail), but only very limited types of writing (sign up to receive someone else's status updates in email, turn email reminders for her- or himself on and off, and join and depart a project).

So while everything other type of data access was done using LINQ, it seemed convenient to handle mutations by non-admin users via stored procedures. Specifically, I needed one right off the bat: any authenticated user - know by the alias - could sign up for status email for a person whose status was to be collected.

The task seemed quite obvious:

-- =============================================
-- Author: Sergey Solyanik
-- Create date: 11/14/2008
-- Description: Adds a subscription
-- =============================================
CREATE PROCEDURE [dbo].[AddSubscriptionToPerson]
@alias nvarchar(15),
@personId int
AS
BEGIN
DECLARE @subscriberId int

SET @subscriberId = (SELECT SubscriberId
FROM Subscribers
WHERE SubscriberAlias = @alias)

IF @subscriberId = NULL -- BUGBUG: '=' does not work!
BEGIN
INSERT INTO Subscribers (SubscriberAlias) VALUES(@alias)
SET @subscriberId = @@IDENTITY
END

IF NOT EXISTS(SELECT 1
FROM SubscriptionsPeople
WHERE SubscriberId = @subscriberId AND
PersonId = @personId)
BEGIN
INSERT INTO SubscriptionsPeople (PersonId, SubscriberId)
VALUES(@personId, @subscriberId)
END
END
Right? Wrong! If @subscriberId is NULL, the following statement:

IF @subscriberId = NULL
SELECT 'IS NULL'
else
SELECT 'IS NOT NULL'
prints out 'IS NOT NULL'! The correct way of tesing for NULL is not comparing with NULL, but using IS [NOT] NULL keyword:

IF @subscriberId IS NULL
SELECT 'IS NULL'
else
SELECT 'IS NOT NULL'

So the version of code that actually works is:

-- =============================================
-- Author: Sergey Solyanik
-- Create date: 11/14/2008
-- Description: Adds a subscription
-- =============================================
CREATE PROCEDURE [dbo].[AddSubscriptionToPerson]
@alias nvarchar(15),
@personId int
AS
BEGIN
DECLARE @subscriberId int

SET @subscriberId = (SELECT SubscriberId
FROM Subscribers
WHERE SubscriberAlias = @alias)

IF @subscriberId IS NULL
BEGIN
INSERT INTO Subscribers (SubscriberAlias) VALUES(@alias)
SET @subscriberId = @@IDENTITY
END

IF NOT EXISTS(SELECT 1
FROM SubscriptionsPeople
WHERE SubscriberId = @subscriberId AND
PersonId = @personId)
BEGIN
INSERT INTO SubscriptionsPeople (PersonId, SubscriberId)
VALUES(@personId, @subscriberId)
END
END
Unfortuately, discovering this was not trivial. You see, IS [NOT] NULL is nowhere near IF in the documentation, and neither it is in the book I was reading. Also, EXISTS works if you put your SQL query that returns NULL in the IF itself, like so:

IF NOT EXISTS(SELECT SubscriberId
FROM Subscribers
WHERE SubscriberAlias = @alias)
THEN...
...but not like this:

SET @id = (SELECT SubscriberId
FROM Subscribers
WHERE SubscriberAlias = @alias)
IF EXISTS(@id)...
Well, what should we expect from a language with the syntax and semantics right out of 1950s. I haven't worked with anything like this since FORTRAN...

Friday, November 14, 2008

Redundancy

"There is little point in building a stored procedure just to run a set of T-SQL statements only once; conversely, a stored procedure is ideal for when you wish to run a set of T-SQL statements many times."

Or shall I repeat it?

"Beginning SQL Server 2008 for Developers", by Robin Dewson.

Wednesday, November 12, 2008

Michael Lewis on the Wall Street collapse

"I’d never taken an accounting course, never run a business, never even had savings of my own to manage. I stumbled into a job at Salomon Brothers in 1985 and stumbled out much richer three years later, and even though I wrote a book about the experience, the whole thing still strikes me as preposterous—which is one of the reasons the money was so easy to walk away from. I figured the situation was unsustainable. Sooner rather than later, someone was going to identify me, along with a lot of people more or less like me, as a fraud. Sooner rather than later, there would come a Great Reckoning when Wall Street would wake up and hundreds if not thousands of young people like me, who had no business making huge bets with other people’s money, would be expelled from finance."

http://www.portfolio.com/news-markets/national-news/portfolio/2008/11/11/The-End-of-Wall-Streets-Boom

If you haven't read the Liar's Poker, I strongly recommend... It's hilarious!

http://www.amazon.com/Liars-Poker-Rising-Through-Wreckage/dp/0140143459

GM in trouble?

Check out what they're paying their CEO...
http://www.reuters.com/article/businessNews/idUSN2534738420080425?feedType=RSS&feedName=businessNews

Tuesday, November 11, 2008

Encrypting data in .NET

Encrypting:
using System.Security.Cryptography;
...
string password;
string encryptedPassword = Convert.ToBase64String(
ProtectedData.Protect(Encoding.UTF8.GetBytes(password), null,
DataProtectionScope.CurrentUser));
Decrypting:
using System.Security.Cryptography;
...
string encryptedPassword;
string password = Encoding.UTF8.GetString(ProtectedData.Unprotect(
Convert.FromBase64String(encryptedPassword), null,
DataProtectionScope.CurrentUser))

Registry in .NET

Writing:
using Microsoft.Win32;
...
const string REGISTRY_KEY = "software\\yourcompany\\yourapp";
...
RegistryKey key = Registry.CurrentUser.CreateSubKey(REGISTRY_KEY);
key.SetValue("user", args[1]);
key.Close();
Reading:
using Microsoft.Win32;
...
const string REGISTRY_KEY = "software\\yourcompany\\yourapp";
...
string user = null;
RegistryKey key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY);
if (key != null)
{
user = (string)key.GetValue("user");
key.Close();
}

Fun with LINQ: database programming tasks in under 10 lines of code

Go to Project->New Item->Data LINQ to SQL classes. After you get the design surface, click on "Server Explorer" (a tab on the right), connect to a database, and drag over tables to the white space in the middle of the screen.

Save the resulting DBML file.

Let's say the DBML file is called Snippets.dbml, and it contains the table People (note that below LINQ class generator converted it to plural "Peoples" - a bit annoying, but... whatever).

Simplest query - get everything:

SnippetsDataContext snippets = new SnippetsDataContext();
var allPeople = from person in context.Peoples
select person;
foreach(People person in allPeople)
{...}
snippets.Connection.Close();
snippets.Dispose();

A simple precondition:

SnippetsDataContext snippets = new SnippetsDataContext();
var activePeople = from person in context.Peoples
where person.IsActive
select person;
foreach(People person in activePeople)
{...}
snippets.Connection.Close();
snippets.Dispose();

A more complicated precondition:

SnippetsDataContext snippets = new SnippetsDataContext();
var activeMikes = from person in context.Peoples
where person.IsActive && person.Name.Contains("Mike")
select person;
foreach(People person in activeMikes)
{...}
snippets.Connection.Close();
snippets.Dispose();

Get only the data you need, with anonymous types:

SnippetsDataContext snippets = new SnippetsDataContext();
var peopleNamesAndIds = from person in context.Peoples
select new { person.PersonId, person.PersonName };
foreach(var p in peopleNamesAndIds)
{
Console.WriteLine(p.PersonId + ": " + p.PersonName);
}
snippets.Connection.Close();
snippets.Dispose();

Modifying data:

SnippetsDataContext snippets = new SnippetsDataContext();
var renameMikesToJohns = from person in context.Peoples
where person.Name.Contains("Mike")
select person;
foreach(People person in renameMikesToJohns)
{
person.PersonName = person.PersonName.Replace("Mike", "John");
}
context.SubmitChanges();
snippets.Connection.Close();
snippets.Dispose();

Adding a row:

SnippetsDataContext snippets = new SnippetsDataContext();
People person = new Person();
person.PersonName = "Bill Maher";
context.Peoples.InsertOnSubmit(person);

Fun with Outlook and .NET

You need to add reference to Microsoft.Office.Interop.Outlook.

Reading email in 11 lines of code:

using Microsoft.Office.Interop.Outlook;
...
Application Outlook = new Application();
NameSpace OutlookNs = Outlook.GetNamespace("MAPI");
OutlookNs.Logon(null, null, true, true);
Folder inbox =
(Folder)Outlook.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Folder destination = GetDestinationFolder();
foreach (object item in inbox.Items)
{
if (item is MailItem)
{
MailItem mail = (MailItem)item;
Console.Write(mail.SenderName + ": " + mail.Subject);
}
}
OutlookNs.Logoff();

Sending email in 12 lines of code:

using Microsoft.Office.Interop.Outlook;
...
Application Outlook = new Application();
NameSpace OutlookNs = Outlook.GetNamespace("MAPI");
OutlookNs.Logon(null, null, true, true);
MailItem mail = (MailItem)OutlookNs.Application.CreateItem(OlItemType.olMailItem);
mail.BodyFormat = OlBodyFormat.olFormatPlain;
mail.Body = "Hello, world!";
mail.Subject = "Sent from C# code snippet!";
mail.Recipients.Add("alias");
mail.Recipients.ResolveAll();
mail.Send();
OutlookNs.Logoff();

Monday, November 10, 2008

Sarah, you’re no Hillary Clinton

“I know Hillary Clinton. Hillary Clinton is a friend of mine. And Sarah, you’re no Hillary Clinton.”

The McCain adviser who leaked that Palin did not know that Africa was not a country comes out of the closet...

http://www.eisenstadtgroup.com/2008/11/10/eisenstadt-the-source-for-sarah-palin-africa-leak-and-proud-of-it/

Reading the comments is spectacularly amusing. How did this country came to having an entire political party that viscerally resents intelligence?

----------------------
Update: likely a hoax. http://www.huffingtonpost.com/2008/11/10/martin-eisenstadt-non-exi_n_142785.html.

The comments are nevertheless hilarious.

Getting back your lost files with Vista

If there is one good thing about Vista compared to XP, it's the new storage stack, which is now on par with the server operating systems such as Windows Server 2003 and 2008.

I am still due to write a post about how to write image-based backup using VSS (volume snapshot services), but just now I used it to save a file that I thought I'd lost.

I was editing code in Visual Studio, hitting Ctl-S to save it every few modifications. Suddenly, a window popped us inviting me to save Program.cs to an alternate location. I cancelled out (first mistake), closed VS (second mistake), and went to the part of the tree where the file was. It was showing in the explorer, but I could not open it.

"Vista..." - I sighed, and rebooted the computer (in reality, I don't have a proof - or even reason to believe that it was Vista that ate the file - it is more likely a bug in Visual Studio that is to blame).

When it came back, the file was not there. Damn. Another reboot, but with "chkdsk /f c:" now to check the file system. No errors, and the file still not there. Luckily, I remembered about VSS and how it is now a part of the client operating system.

What is VSS, or "Volume Snapshot Services"?

It's a service in the operating system that periodically detects which clusters on the disk are used by the file system. Then, when any of these clusters is overwritten, before writing the new data, it copies the old information in an area of the disk reserved for it, and records it.

Then, the (read-only) image of the original (at the time of the snap) disk state can be reconstructed and mounted. So if the file system got corrupted, or a file overwritten or deleted, you can get your data back.

To do it, right-click on a file (if it's still present), or a folder, or a drive, and click on "Restore Previous Version..." menu item.



A dialog box will open inviting you to select from a bunch of snapshots that the system had taken for you at various times in the past:



Select the version, and the normal explorer window will open, pointing to the mounted image of your disk as it existed on the given date.



Find your file, and voila - you can copy it to where it should be.

Saturday, November 8, 2008

The next Depression

This promises to be a crisis of epic proportions.

People are comparing it with the Great Depression, but there is one huge difference: during the Depressions US still had it manufacturing base intact. It was a financial and social crisis, but the country had robust physical infrastructure to cope with it.

This is not the case today: US infrastructure is largely gone, and we're very quickly losing our R&D base.

I've realized how far this has gone when I took a trip to Taipei in 2003. For a large part of its history, Taiwan was one big factory. Products were designed in the United States and built here. By 2003 however manufacturing has moved on to the mainland China, and R&D moved in: we visited 5-6 companies that were building routers, and they were all purely R&D shops with manufacturing outsourced to China.

Quanta Computer in Taiwan is the largest laptop company in the world. You probably have not heard about it: the laptops that it designs (in Taiwan) and makes (in China) usually sell under Dell, SONY, and HP brand names. In 2006 it produced roughly 60% of all laptops made in the world. It also makes servers: about 40% of them.

Back in 2006 the joke that went around Microsoft was this: "Dell people think that they outsourced the manufacturing to Quanta, and Quanta people think that they outsourced marketing and distribution to Dell". Very true: a lot of what's left in the US is just that - marketing and distribution. We no longer make stuff - we just buy and sell it. With the money borrowed from Chinese.

The end of 90s were a brief respite: the pyramid scheme of .com boom had temporarily returned engineering to the top. Not for long: the enrollments into computer science programs are now below 1995 levels, US high school scores in math and science rank around 20th place in the world - below most European and a few Asian countries.

The universities churn out people who are largely incompetent. When I was interviewing graduates in China, it was immediately obvious that although there was a wide distribution in intellectual capabilities, they have all studied hard and came out of school with solid knowledge of computer science and math.

When I interview college graduates here, there is the same wide variety of IQ - and almost universal lack of basic training. At school they mostly had worked in large teams where there was one nerd that did everything, and everybody else managed process and collected customer requirements.

Our social protection net is in probably worst shape it's ever been since the New Deal. The unevenness of income distribution is as high as it's ever been: an average CEO makes 400 times the income of an average worker. This is compared to 20-40 range it's been throughout much of the history: the growth took off when Reagan lowered the upper tax bracked from 70% to 28% (it has since moved back a little to 36%).

The income distribution here is more similar to the Middle Ages than to any modern developed society.

The insane compensation packages at the top are the source of our current predicament: they incent a rationally-behaving CEO to maximize the short-term profit (after which he or she simply cashes out) at the expense of the long-term risk.

Meanwhile, the number of people lacking basic health insurance is as high as it's ever been, and the percentage of people who qualify for government assistance is as low as it's been as well, with state budgets weakened to the breaking point.

So now that we're in financial crisis, we don't have either manufacturing, or R&D capacity to lean on, nor health care or protection net to carry us through the bad times. To wit: even illegal immigration from Latin America is at its lowest point in decades.

We're in deep trouble.

So what do we do? The future depends on the new Democratic administration's willingness to take the reins, and do it vigorously.

They have the power to do a lot: strong majorities in Senate and House, and the Presidency. What they do not have is time: if the country is not on the right track in two years, if there's no improvement in the situation - beyond any reasonable doubt - they will lose the mandate, and the Obama government will be powerless.

Democrats should be quick, effective, and ruthless. Any talk about bipartisanship must end now: there's simply no time to reason with the Republican wackos in Congress - the moderates of that party are now largely gone anyway, and what's left are the crazies from the slave states, both geographically and mentally.

First and foremost, the Democrats need to take control of the media. They should push through legislation that breaks down enormous conglomerates that serve primarily corporate interests, the Rupert Murdoch epmire being first and foremost focus. Something akin to trust-busting efforts of Teddy Roosevelt, only directed at Faux News.

The discourse in the country must move away from infotainment that feeds the idiots the line that they are the greatest, smartest, most hardworking idiots in the best country in the world to actual information and informed deliberation. And yes, fewer ads :-)!

In parallel, they should break the lobbying industry. Now or never! The Deomcrats are at an enormous advantage today: with the strength of the grass root, they can survive (and win) without the lobbyists, unlike the Republicans. This will help the Democrats to solidify their power, and the government to start making the decisions that are actually good for the people, not industries and foreign countries.

Nationalize the health care. The elephant in the room that is never mentioned when the rising costs are discussed is that the lion's share of the money goes to the doctors. It's not to the malpractice insurance (<10%). Not the equipment, and not the drugs: the bottom quartile of doctors in this country make more money than the top quartile of the engineers. There's no reason for this other than the current broken health insurance system, which disintermediates the costs.

Fixing the health care is one of the few instances where the interests of the corporations and the people are identical (the fact that the companies have to pay the health care costs of their workers in the US puts them at a huge disadvantage compared to their competitors in Europe). The nationalized healthcare will give the voters immediate benefit, and the reason to vote for Democrats again in two years.

Invest in the education - big time. Literally, pour money into it. The teachers should have one of the best paying jobs in the country, and right now it's one of the worst. As a result, US's Sunday school education is better than the regular one, and we keep churning out religious fanatics. Better education correlates negatively with voting Republican, so investment here should help Democrats keep on their power.

Create massive programs for public works - and research investments. Energy independence, putting a man on Mars, rebuilding the physical infrastructure of the country - all at once. Massive spending is the only thing that can arrest the spread of the financial crisis, keep it from turning into multi-decade depression. Luckily, we're so behind in terms of progress, that the opportunities abound.

Finance these public works by devaluing the dollar and raising the taxes in the upper income bracket. The dollar os way too expensive, and it does not help: the paper should not stand in the way of the progress. Especially when much of the paper is held by foreing investors anyway :-). Cheap dollar will help revitalize manufacturing and R&D here in the US.

Higher taxes will restore the right set of incentives for the executive class: instead of get-rich-quick scheme, being a CEO will be what it was before here, and what it is now anywhere else in the developed world: a respectable, highly-paid job with high responsibilities.

Protect domestic manufacturing and R&D with tariffs. It's a myth that a country can live on moving the borrowed money from one pocket to another. To survive, we need to start - for once - making something useful again. And there's no way to do it without the base. Let's have the industrial revolution again!

Finally, investigate the abuses of the previous administration. Iraq, the torture, the wiretapping, the role of lobbyists in government must not be swept under the carpet: there's a wonderful opportunity to (1) get a lot of Republicans in jail where they belong, and (2) create and reinforce in the public mind the mental equivalency between the words "Republican" and a "crook". This association could last for a generation or two - it is very much in Democrats' interests to not pass on the opportunity.

Monday, November 3, 2008

Mercer for President!

Lee L. Mercer Jr. Welcomes You!

My Campaign Theme

The United States Government must regulate government sleepers and government regulations authorized thought, ideas, acts, actions, rights, wrongs, controversies, facts, issues and circumstantial evidence through intelligence research, law research, law enforcement research and criminal law research implementing ROTC communications research innovating education national and international.

My Platform

My platform for President of the United States Of America is Criminal Law. It is developed from my Method of Education. I was ordered to create and or invent by the United States Army that is now intact regulating the United States Government protecting it through Military Intelligence Computerization Management a new Disipline I invented and the Administration of Criminal Law Laws across the board.

My Direction

The United States Government education will perfect the vindication of it’s government regulating it’s directions and resources requirement by the law only.


http://www.mercerforpresident2008.com/home.html

Sunday, November 2, 2008

Beginning SQL Server 2008 for Developers: a book review

http://www.amazon.com/Beginning-SQL-Server-2008-Developers/dp/1590599586/ref=sr_1_1?ie=UTF8&s=books&qid=1225678034&sr=8-1

Short version: this book's information density could be much improved.

Long version: I picked this up because I am building a database app (a little snippet app which the devs on my team could use for status reports), and I needed to learn about SQL Server. I never used it before, so the book looked like a match: I am both a dev, and a database novice.

On the positive side, this book does provide information. On the negative side, the information it provides could be packed in quarter of the space. It is very, very verbose. While reading it, I could not shake off a feeling that the author was trying to fill (contractually?) pre-determined number of pages.

The book is actually very basic: it shows you how to create a database, but does not go into depth on any topic it discusses: best practices, performance considerations, and SQL 2008 specifics are some times mentioned, but never covered.

It does show you how to create a database (using UI and TSQL), add a table, set up basic relationships, back the database up, and add data: the minimum one must know to start using the database, but not enough to make one a database developer.

Lacking the depth (and breadth), the author compensates by sheer verbosity. Every dialog used is presented as a screen shot (no less than 25% of the book consists of these screen shots). Every parameter of a SQL statement is given a description, usually a perfunctory one:
  • DESCRIPTION: A description of the backup (p.193)


Sometimes, it gets to ridiculous proportions. On page 191 there is a half-page template for the BACKUP DATABASE statement. In the next paragraph, the same half page of text is repeated again - with one line added to specify a file group parameter.

Here is its description of the SQL backup modes, page 188:

"The first possibility, full backup, is straightforward. Selecting the Full option ensures that the whole database will be backed up. All the tables, the data, and so on are backed up if we use this option. We also back up enough of the transaction log (transactions committed via code, but not physically applied to the relevant tables at the point of backup). This backup would be seen as any starting point for a restore from a database failure.

The second possibility is the differential backup, also known as an incremental backup. Use the Differential backup option when the circumstances are such that a full backupis either not required or not possible. This just performs a backup on data changed since the last backup. For example, we may take a full backup on the weekend and then a differential backup every night. When it comes to restoring, we would restore the weekend full backup, and then add to that the latest differential backup taken from that point. A word of warning here: if you do take a week's worth of differential backup, and you back up to magnetic tape rather than a hard drive, do keep at least enough different tapes for each differential backup. Therefore, use a complete backup when necessary and then in the interim, use a differential backup."

What this says in so many words is: full backup backs up the entire database (duh!), and differential backup backs up the data changed since the full backup. What it does not say is when is differential backup really should be used (other than "when appropriate"), how does the system guarantee the consistency of the data on backup (it does it by using VSS), etc.

How annoying all this really is depends on how the individual reader processes the information. I ended up in a mode where I was quickly scanning through the text in search of information. I lost a bit of time doing this, and I probably glossed over a thing or two that was important, and worth knowing. The book is still probably better than reading the documentation, but if I were buying it again, I would buy something else.