Friday, October 7, 2011

Python script to backup/restore Azure Storage blobs

Recently I wrote python script to backup/restore all blobs from Windows Azure Storage account.
You can find it on github
https://github.com/vsevolodp/azure-storage-backup
or download as a zip archive.

To see how to use it run:
  $ python as-backup.py

See README file for more info about supported fatures

Monday, September 19, 2011

How to migrate Azure Storage data after upgrade to Azure SDK 1.5

After Azure SDK 1.5 installation complete you will see that all your data disappeared from Storage. This is because installation will create new database in your SQL Express instance. But all your data still there.

Microsoft SQL Server Management Studio

As you can see I had previous database created 2009-09-19.

So you need to move your data into new database. To do it open new query editing window and copy/paste/run the script below (double-click to Select all).

And don't forget to change names of the databases!
BEGIN TRANSACTION
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[BlobContainer]
 ([AccountName]
 ,[ContainerName]
 ,[LastModificationTime]
 ,[ServiceMetadata]
 ,[Metadata])
SELECT [AccountName]
      ,[ContainerName]
      ,[LastModificationTime]
      ,[ServiceMetadata]
      ,[Metadata]
  FROM [DevelopmentStorageDb20090919].[dbo].[BlobContainer]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[BlockData]
 ([AccountName]
 ,[ContainerName]
 ,[BlobName]
 ,[VersionTimestamp]
 ,[IsCommitted]
 ,[BlockId]
 ,[Length]
 ,[Data])
SELECT [AccountName]
      ,[ContainerName]
      ,[BlobName]
      ,[VersionTimestamp]
      ,[IsCommitted]
      ,[BlockId]
      ,[Length]
      ,[Data]
  FROM [DevelopmentStorageDb20090919].[dbo].[BlockData]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[Blob]
 ([AccountName]
 ,[ContainerName]
 ,[BlobName]
 ,[VersionTimestamp]
 ,[BlobType]
 ,[CreationTime]
 ,[LastModificationTime]
 ,[ContentLength]
 ,[ContentType]
 ,[ContentMD5]
 ,[ServiceMetadata]
 ,[Metadata]
 ,[LeaseId]
 ,[LeaseTypeInt]
 ,[LeaseDuration]
 ,[LeaseEndTime]
 ,[SequenceNumber]
 ,[IsCommitted]
 ,[HasBlock]
 ,[UncommittedBlockIdLength]
 ,[MaxSize]
 ,[FileName])
SELECT [AccountName]
      ,[ContainerName]
      ,[BlobName]
      ,[VersionTimestamp]
      ,[BlobType]
      ,[CreationTime]
      ,[LastModificationTime]
      ,[ContentLength]
      ,[ContentType]
      ,[ContentMD5]
      ,[ServiceMetadata]
      ,[Metadata]
      ,[LeaseId]
      ,[LeaseTypeInt]
      ,[LeaseDuration]
      ,[LeaseEndTime]
      ,[SequenceNumber]
      ,[IsCommitted]
      ,[HasBlock]
      ,[UncommittedBlockIdLength]
      ,[MaxSize]
      ,[FileName]
  FROM [DevelopmentStorageDb20090919].[dbo].[Blob]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[CommittedBlock] 
 ([AccountName]
 ,[ContainerName]
 ,[BlobName]
 ,[VersionTimestamp]
 ,[Offset]
 ,[BlockId]
 ,[Length]
 ,[BlockVersion])
SELECT [AccountName]
      ,[ContainerName]
      ,[BlobName]
      ,[VersionTimestamp]
      ,[Offset]
      ,[BlockId]
      ,[Length]
      ,[BlockVersion]
  FROM [DevelopmentStorageDb20090919].[dbo].[CommittedBlock]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[Page]  
 ([AccountName]
      ,[ContainerName]
      ,[BlobName]
      ,[VersionTimestamp]
      ,[StartOffset]
      ,[EndOffset]
      ,[FileOffset])
SELECT [AccountName]
      ,[ContainerName]
      ,[BlobName]
      ,[VersionTimestamp]
      ,[StartOffset]
      ,[EndOffset]
      ,[FileOffset]
  FROM [DevelopmentStorageDb20090919].[dbo].[Page]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[CurrentPage]  
 ([AccountName]
 ,[ContainerName]
 ,[BlobName]
 ,[VersionTimestamp]
 ,[StartOffset]
 ,[EndOffset])
SELECT [AccountName]
      ,[ContainerName]
      ,[BlobName]
      ,[VersionTimestamp]
      ,[StartOffset]
      ,[EndOffset]
  FROM [DevelopmentStorageDb20090919].[dbo].[CurrentPage]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[QueueContainer]
 ([AccountName]
 ,[QueueName]
 ,[LastModificationTime]
 ,[ServiceMetadata]
 ,[Metadata])
SELECT [AccountName]
      ,[QueueName]
      ,[LastModificationTime]
      ,[ServiceMetadata]
      ,[Metadata]
  FROM [DevelopmentStorageDb20090919].[dbo].[QueueContainer]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[QueueMessage]  
 ([AccountName]
 ,[QueueName]
 ,[VisibilityStartTime]
 ,[MessageId]
 ,[ExpiryTime]
 ,[InsertionTime]
 ,[DequeueCount]
 ,[Data])
SELECT [AccountName]
      ,[QueueName]
      ,[VisibilityStartTime]
      ,[MessageId]
      ,[ExpiryTime]
      ,[InsertionTime]
      ,[DequeueCount]
      ,[Data]
  FROM [DevelopmentStorageDb20090919].[dbo].[QueueMessage]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[TableContainer]
 ([AccountName]
 ,[TableName]
 ,[LastModificationTime]
 ,[ServiceMetadata]
 ,[Metadata]
 ,[SchemaXml])
SELECT [AccountName]
      ,[TableName]
      ,[LastModificationTime]
      ,[ServiceMetadata]
      ,[Metadata]
      ,[SchemaXml]
  FROM [DevelopmentStorageDb20090919].[dbo].[TableContainer]
GO

INSERT INTO [DevelopmentStorageDb20110816].[dbo].[TableRow]  
 ([AccountName]
 ,[TableName]
 ,[PartitionKey]
 ,[RowKey]
 ,[Timestamp]
 ,[Data])
SELECT [AccountName]
      ,[TableName]
      ,[PartitionKey]
      ,[RowKey]
      ,[Timestamp]
      ,[Data]
  FROM [DevelopmentStorageDb20090919].[dbo].[TableRow]
GO

COMMIT TRANSACTION
GO

Tuesday, April 26, 2011

Just finished TOPCODER SRM 504 DIVISION 2 competition. Solved 250 and 500 point problems.

Here are my solutions in C#

using System;

public class ComparerInator
{
    public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
    
    public int makeProgram(int[] A, int[] B, int[] wanted)
    {
        if (test(A, B, wanted, f_a) || test(A, B, wanted, f_b))
            return 1;
        if (test(A, B, wanted, f_ab) || test(A, B, wanted, f_ba))
            return 7;
            
        return -1;
    }
    
    bool test(int[] A, int[] B, int[] wanted, Func<int, int, int> f)
    {
        for (int i=0; i < A.Length; i++)
        {
            if (f(A[i], B[i]) == wanted[i])
                continue;
                
            return false;
        }
        
        return true;
    }
    
    int f_a(int a, int b)
    {
        return a;
    }
    
    int f_b(int a, int b)
    {
        return b;
    }
    
    int f_ab(int a, int b)
    {
        return a<b?a:b;
    }
    
    int f_ba(int a, int b)
    {
        return a<b?b:a;
    }
}

using System;
using System.Text;

public class MathContest
{
    public int countBlack(String ballSequence, int repetitions)
    {
        StringBuilder sb = new StringBuilder(ballSequence.Length * repetitions);
        for (int i = 0; i < repetitions; i++)
            sb.Append(ballSequence);
            
        s = sb.ToString();
        
        pos = -1;
        invert = false;
        direction = 1;
        end = s.Length - 1;
        
        int count = 0;
        
        char ball = get_next();
        while (ball != (Char)0)
        {
            if (ball == 'B')
                count++;
            ball = get_next();
        }
        
        return count;
    }

    string s;
    int pos;
    bool invert;
    int direction;
    int end;

    char get_next()
    {
        if (pos == end)
            return (Char)0;    
            
        pos += direction;
        char ch = s[pos];
        
        if (invert)
        {
            if (ch == 'B')
                ch = 'W';
            else
                ch = 'B';
        }
        
        if (ch == 'B')
            invert = invert ? false : true;
        else
        {
            int t = end;
            end = pos + direction;
            pos = t + direction;
            direction = direction == 1 ? -1 : 1;
        }
        
        return ch;
    }
}
Unfortunately I've made a mistake in 500-point problem. Instead of
end = pos + direction;
            pos = t + direction;
I wrote
end = pos;
            pos = t;
so my solution was successfully challenged and gave me zero points.

More then it - it was my first competition on TopCoder and there was a problem running the engine. So results are not go to rating. Well... next time.

Sunday, November 14, 2010

How to decode Encoded-Word header values in emails

Here is C# code to decode Encoded-Word header values in emails.
Features:

  • supports encoding of multi-line values
  • supports both Q- and base64 encoding
  • passes all samples in RFC 2047, section "8. Examples"
public class EncodedWordEncoding
    {
        public static string Decode(string encodedText)
        {
            if (encodedText == null)
                return null;

            var regex = new Regex(@"=\?(?<charset>.*?)\?(?<encoding>[qQbB])\?(?<value>.*?)\?=");
            var encodedString = encodedText;
            var decodedString = string.Empty;
            var encodedWordBefore = false;

            while (encodedString.Length > 0)
            {
                var match = regex.Match(encodedString);
                if (match.Success)
                {

                    // If the match isn't at the start of the string, copy the initial few chars to the output
                    var beforeMatch = encodedString.Substring(0, match.Index);

                    // Filter out space chars between encoded words
                    if (encodedWordBefore)
                    {
                        var regex2 = new Regex(@"(\r?\n|\r)*[ \t]+");
                        var match2 = regex2.Match(beforeMatch);
                        if (match2.Success && match2.Value == beforeMatch)
                            beforeMatch = "";
                    }

                    decodedString += beforeMatch;

                    var charset = match.Groups["charset"].Value;
                    var encoding = match.Groups["encoding"].Value.ToUpper();
                    var value = match.Groups["value"].Value;

                    var contentEncoding = Encoding.GetEncoding(charset);

                    if (encoding.Equals("B"))
                    {
                        // Encoded value is Base-64
                        var bytes = Convert.FromBase64String(value);
                        decodedString += contentEncoding.GetString(bytes);
                    }
                    else if (encoding.Equals("Q"))
                    {
                        decodedString +=
                           QuotedPrintableEncoding.Decode(value, contentEncoding).Replace("_", " ");
                    }
                    else
                    {
                        // Encoded value not known, return original string
                        // (Match should not be successful in this case, so this code may never get hit)
                        decodedString += encodedString;
                        break;
                    }

                    // Trim off up to and including the match, then we'll loop and try matching again.
                    encodedString = encodedString.Substring(match.Index + match.Length);

                    encodedWordBefore = true;
                }
                else
                {
                    // No match, not encoded, return original string
                    decodedString += encodedString;
                    break;
                }
            }

            return decodedString;
        }
    }

    public static class QuotedPrintableEncoding
    {
        public static string Decode(string text, Encoding encoding)
        {
            if (text == null)
                throw new ArgumentNullException("text");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            if (text.Length == 0)
                return text;

            text = text.Replace("=\r\n", "");

            var regex = new Regex(@"(=[0-9A-F][0-9A-F])+", RegexOptions.Multiline | RegexOptions.IgnoreCase);

            return regex.Replace(text, m =>
                {
                    if (m.Value.Length % 3 != 0)
                        throw new InvalidOperationException("Unexpected match length.");

                    var bytes = m.Value.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(v => byte.Parse(v, NumberStyles.HexNumber));

                    return encoding.GetString(bytes.ToArray());
                });
        }
    }

Code used from klaas114's post and Dave's post.

UPDATE 31 Jan 2010: implemented my own quoted-printable decoder.

Monday, October 4, 2010

How to move Microsoft Help Library (Visual Studio 2010)

On the Help Library Manager page you can read that you can not move the content of the library.
I've found a couple of ways to do this actually.


Hacking windows registry
You can change this setting in the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Help\v1.0\LocalStore

This is a general direction and may change in next versions of the Microsoft Help Library.
  1. Copy your files to new location
  2. Change the key value
  3. Start the Help Library Manager, go to Settings and check the path is correct
  4. Click the Check for updates online link to check your content


First time run... Again
Also you can tell the Help Library Manager to start as first time and then set a new location.
  1. Start notepad or your favorite editor with administrator privileges
  2. Open the file "C:\Program Files\Microsoft Help Viewer\v1.0\HelpLibManager.exe.config"and change FirstTimeRun key value to True
  3. Start the Help Library Manager and set new location
Finally
Open file "HelpLibrary\manifest\queryManifest.N.xml" (mine is queryManifest.4.xml) and correct catalogPath and contentPath values.
Close the Help Library Agent if it's running (look at the tray area).