Why I switched to Crashplan
There are several cloud backup products on the market and I’ve dabbled in quite a few. BeInSync was my first true love – right up to the point Phoenix Technologies shut down operations. That was then replaced by iDrive – which is still on the wife’s PC today – albeit on a short term lease of life. It had been on my PC aswell but after the move to Windows 7 and Comodo it stubbornly refused to play ball (which was odd because wifey has the same configuration and there it works fine). So last March I threw myself into Carbonite and really liked the way it put those lil’ ol’ red/greeen markers on each file to indicate it’s freshness in the cloud. However it too had issues such as not playing ball with my Outlook PST files in a sensible and meaningful fashion.
I should probably add here that before I settled on iDrive I had also briefly auditioned Mozy but quickly threw that idea out.
So at this juncture I was left with iDrive ion the SO’s PC, Carbonite on mine and Genie Timeline on both performing local backups. Trouble is, I’m a control freak and none of this was giving me the confidence that all was really well on both PC’s – yet alone my Linux Mint (yeah, I switched back to Mint!) Netbook which was left swinging in the wind with a collection of important files on there left from various vacations (which is when the Netbook get’s pressed into action the most).
Crashplan made it’s presence known through the strongest advertising I’d seen myself. Every time I flicked on Evernote there was a prod to try it out (I used Evernote a lot). Then the pushed through their Thanksgiving Cyber-Monday sale which I still refused to take a bite out (mainly because it didn’t address at the time there sudden disappearance of Crashplan+), even through the short term sale of a 3 years 3 PC offer seemed tempting.
Now, what made me make the jump was the sales structure AFTERWARDS. Sure the 3 year (for the price of 2 years) 3 PC deal had vanished but in it’s place was a 4 Year ‘All you can eat’ plan. This was indeed tempting – so much so that I quickly installed a copy on my PC as a 30 day trial and began thro throw more and more at it.
Here’s what I liked so much:
- Multiple PC’s in the same household are all covered
- Windows, Linux or Mac makes no odds – still covered.
- Backup to cloud, local drive or another PC – snap (no more need for Genie Timeline 2.0)
- Email and Twitter both utilized for alerting of failed backups.
- Multiple backup sets (e.g. my AppData stuff I backup only to a local drive and another PC)
- Single source backup – no mo longer need third party applications to backup outside of the cloud.
So after auditioning it myself (I dogfood pretty much everything before it get’s put on my wife’s PC) – I came out a true believer. We checked the budget, confirmed we had the cash for a 4 year upfront payment and set the ball rolling
I then threw the kitchen sink at it. All my original sized pictures, MP3’s AppData – the whole shebang and it ate it all up with aplomb and gusto.It finished the wife’s full backup to the cloud a few days ago which means that I know can finally shut off the iDrive and Genie spigots.
My backup’s still running, but only because my 50GB MP3 collection has been set to backup during the night time only – I still have 3 months of Carbonite subscription left on my PC so I’m not so worried about getting it done ASAP – ‘sides, I do like my bandwidth!
So now I’m happy – less to maintain and more completeness – what a combo!
Migrating our world to Google Apps
Those who know me will know I’ve not been the biggest fan of Google of late. I still think many of their business strategies may be on the dodgy side (read Capturing emails and passwords from unsecured WiFi access points amongst others).
However I will have to admit that in terms of providing a unified cloud for governing ones life (email, documents, tasks, calendar etc) then they do have more than an edge on their competitors. Granted Microsoft has their Office Live and Windows Live sites however it doesn’t do much for you on the email front unless you’re an educational establishment – and I needed a total a solution as I could get.
My spouse and I have both been long time Outlook users and I’ve been using Outlook 2010 for the last 2-3 months, however given the fact that we’re both wanting more ‘anywhere anytime’ access to our data and the fact we’re both getting into more social networking, it fell upon my shoulders to find a solution that would make both of us happy.
Where Microsoft has Live and Outlook then, Google has Thunderbird (or Evolution or any other application that does IMAP – including Outlook). And being a bit of a control freak (in other words I like to have a central ‘command’ console whenever possible) Google Apps Standard seemed to fit the bill for myself and ‘she who must be obeyed’.
Currently we use 1&1 for our email handling – I also use it to host all the images etc. in this blog, in addition to allowing other family members to use it for their web needs as well). Being paranoid buggers, neither myself, nor my better half like using single email addresses for everyone. So instead we generate email random addresses for each company we contact – that way when an address should somehow find its way onto a Spam list (as 4-5 have these last 2 years) we can simple blow that address away and we’re back to a spam free existence. So given our investment already in 1&1 I was loath to drop it – so I didn’t and instead incorporated it into my overall solution and ended up simply forwarded emails to the new address (which was especially nice since it allowed me to run both systems side by side for a while).
Utilizing 1&1’s domain DNS management features (it allowed me to easily modify the MX records and CNames as required) and free sub-domains I was able to set up a new sub-domain for all my mobile communications need and attach that to Google apps. This allowed me to set up friendly URL’s to each service (Mail, Calendar etc).
Then came configuring GMail accounts for us both making sure we kept as much of our existing Outlook functionality as possible (shared calendars and tasks using Sync2Pst) whilst gaining more functionality (unified view of the data, regardless of which OS, PC or mobile device we use). This necessitated using Thunderbird (I did try Evolution which ran OK on my Ubuntu box but failed miserably to work on the Windows port) using a handful of addons (Lightening, Google Calendar Provider for Lightening and the rather excellent although still in beta (for v3 anyway) gContactSync) to name but three. With this in hand I was able to achieve my first directive from the boss – no duplication of work – in other words should she delete an email using (the soon to arrive) Droid Incredible she wanted it gone everywhere. Equally if she updated a contact in Thunderbird, she’d expect to see the same update on her phone. The sharing of calendars was the easiest bit using Google’s direct calendar sharing facilities.
This still leaves us with some holes which we’ve either got a workaround for (tasks are Calendar entries) or no solution (sharing contacts between us) however I continue to look for answers as and when they should transpire.
Google apps also gives us access to several other shared applications what we can use a single sign on for which makes the deal even better including a HelpDesk app which allows her to get me to fix computer issues without nagging me every 5 minutes!
Now, this is not perfect I’ll admit, however given the alternatives (or lack thereof) it’s the best solution (especially given that we’re both about to get Droid’ed).
I’m also hoping that Google do begin to migrate Picasa soon to Google Apps since that would make handling our pictures easier and please Google, bring out an API for tasks!
My brief sojourn with Linux Mint is over…
Well, it was a brief, but informative party. However now the guests have all gone home I’m left looking at removing Linux Mint from my laptop.
Linux Mint I heard, was meant to be the most user friendly version of Linux one could get. However I myself found it kludgy and it felt just a tad bit hostile. Configuring and installing Software packages I found somewhat counter-intuitive – first of all I did like the idea that one has to select packages and libraries, just to say, grab a copy of Evolution. Secondly I found it surprising that the installation would then sit there with a rather obscure ‘waiting for lock’ message. It took me a while to realize the lock was the package browser (or whatever it’s called).
Compiz had it’s own challenges and I was forced to spend some time surfing the web to find out what it could – and couldn’t do. Cute effects but still a bit of a pain to configure. Also, not helping Mint was the failure to launch the UFW GUI from the main GUI window. Had to again surf the web to find out how to launch it manually.
And all this concerns me; I’ve been a long time Windows user at home (and predominantly at work). The Windows 7 install was simple and I found everything worked out the box. Dialog boxes were informative and well designed and I found it so much easier to navigate. Mint felt like a major step backwards and I was going to be hard pushed to convince my partner to allow me to put Mint on the family Asus 1008 eeE PC netbook.
This however is not the end of my return to Linux. Last night I decided to download a Live CD copy of Ubuntu 10.04 LTS onto a wee lil’ USB Stick and did a Live Boot of that onto the netbook (which currently still runs the default XP O/S).
What a difference it felt like! Right from the Get Go I felt welcomed into Ubuntu’s warm embrace – this was a Linux distro that seemed to wanted me as a friend. I was happy to see many of the standard applications were pre-installed and ready to rock and within just a few minutes I’d already had Evolution configured and syncing to my Google Calendar (yeah, I know it all get’s blown away when I reboot, but this was a PoC test only).
I’ll be interested to see if this feeling translates to a full-blown laptop install. I hope so because I’m seriously considering putting Ubuntu on the Netbook this weekend (if the other [and more important] half gives me the go-ahead). However in the meantime I think I’ll be replacing Mint with Ubuntu on the laptop to see how well it goes there.
In the meantime I’ve left Ubuntu running on the Asus and let my partner test drive it for a few days to see how she feels about it.
Fingers crossed!
Quest Spotlight 7.0 and “Collection: ‘IndexLatchWaits’ failed : Violation of UNIQUE KEY Constraint…” error
If you’ve just installed or upgraded to Quest Spotlight 7.0 and and getting this odd error for this counter then get Support to send you version 7.5.0.4648 of QS_IndexLatchWaitTimes.sql.
The reason for the exception is because it’s not taking Schema’s into account when inserting unique values into a temporary table, thus the 7.0 RTM version currently errors out if you have the same constraint or index name for the same table for tables under different schemas.
The same script affects both 2005 and 2008 so the patch will need to be installed in two locations – Quest will (should) provide all the details…
Back again….
Well, it’s been somewhat of a long absence, however I’m back again (albeit with a different blog host) and psyching myself up for some more strangely spurious Random Thunking…
Deploying signed assemblies in a single script
I’ve been writing a set of routines to control my database backups recently and one part of this was a CLR User Defined Data Type I’d created that allows some rudimentary file handling (with the appropriate security). By it’s very nature this assembly required the EXTERNAL ACCESS privilege and this is where the head-scratching came about.
Liking clean install scripts with minimal payloads (single scripts are easier to check into Source Code and deploy across multiple environments) I needed some method of encapsulating the deploy and ensuring the appropriate asymmetric key, users etc. were created. However normally this would require either the key file or the assembly DLL to be copied along with the .Sql script – and this would break my 1 script rule! So next idea was to create the asymmetric key from the assembly directly within Sql server – but I couldn’t do that until I’d installed the assembly which would fail because it required the EXTERNAL ACCESS privilege; Thus leading to another game of Chicken and Egg.
The solution was remarkably obvious – use a temporary SAFE assembly to create the asymmetric key then dispose of it directly afterwards – after all the assembly is only required at this juncture to create the asymmetric key.
The first section of the script deals with previous execution cleanups etc:
- Use RandomThunks
- ————/ Start stage 1 : Drop previous objects /————————————————–
- If Exists ( Select 1 From sys.assembly_types As T Inner Join sys.schemas As S On T.schema_id = S.schema_id Where T.name = N'SqlFile' And S.Name = N'Maintenance.Database.Archives')
- Drop Type [Maintenance.Database.Archives].SqlFile;
- If Exists (Select 1 From sys.assemblies Where name = N'RandomThunks.CLR.SqlServerFileUDT' and is_user_defined = 1)
- Drop Assembly [Skipjack.CLR.SqlServerFileUDT];
- – This next key should never exist when we run this as it's only use to create the asymmetric key before we Grant the External Access right to it.
- If Exists (Select 1 From sys.assemblies Where name = N'TEMPORARY. DO NOT USE!' and is_user_defined = 1)
- Drop Assembly [TEMPORARY. DO NOT USE!];
- If Exists ( Select 1 From sys.server_principals Where name = 'SqlServerFileUDTUser' )
- Drop Login SqlServerFileUDTUser;
- If Exists ( Select 1 From sys.asymmetric_keys Where name = 'SqlServerFileUDTKey' )
- Drop Asymmetric Key SqlServerFileUDTKey;
- ————/ End stage 1 : Drop previous objects /—————————————————-
And the second part deploys the assembly with the requisite privilege:
- ————/ Start stage 2 : Object Creation /——————————————————–
- Declare @Assembly VarBinary(MAX);
- Set @Assembly = 0x4D5A9000030000000…
- If Not Exists ( Select 1 From sys.schemas Where Name = 'Maintenance.Database.Archives')
- Exec sp_ExecuteSql N'Create Schema [Maintenance.Database.Archives]';
- – Create a temporary assembly that we'll use to build the Asymmetric Key from
- Create Assembly [TEMPORARY. DO NOT USE!] Authorization dbo
- From @Assembly
- With Permission_Set = Safe;
- Create Asymmetric Key SqlServerFileUDTKey
- From Assembly [TEMPORARY. DO NOT USE!];
- – Drop the temporary assembly – it's use is over.
- Drop Assembly [TEMPORARY. DO NOT USE!];
- Create Login SqlServerFileUDTUser
- From Asymmetric Key SqlServerFileUDTKey;
- – This needs to be run at the Server level – encapsulating it in a sp_ExecuteSql allows the script to be DB name agnostic.
- Exec sp_executeSql N'
- Use master;
- Grant External Access Assembly
- To SqlServerFileUDTUser;';
- – This is the real assembly
- Create Assembly [Skipjack.CLR.SqlServerFileUDT] Authorization dbo
- From @Assembly
- With Permission_Set = External_Access;
- Create Type [Maintenance.Database.Archives].SqlFile
- External Name [RandomThunks.CLR.SqlServerFileUDT].SqlFile;
- ————/ End stage 2 : Object Creation /———————————————————-
Sql Agent Session Storage
I’ve been fiddling around with some jobs recently that required values to be kept from one job step to another. Not finding anything much exciting I went for plan Z – roll my own.
They’re simple procedures but do work nicely.
First I create a Schema that everything will be bundled under:
- If Not Exists ( Select 1 From sys.schemas Where Name = 'Aracs.Utilities.Jobs')
- Exec sp_ExecuteSql N'Create Schema [Aracs.Utilities.Jobs]';
Now we’ll need a backing store:
- Create Table [Aracs.Utilities.Jobs].SessionSaverStore
- (
- JobId UniqueIdentifier Not Null
- ,ParameterName NVarChar(128) Not Null
- ,Value Sql_Variant Null
- );
Next I create the SessionDestroyer Procedure (since it can be called from the next one this keeps the dependencies happy and calm):
- If Object_Id('[Aracs.Utilities.Jobs].SessionDestroyer') Is Null
- Exec sp_ExecuteSql N'Create Procedure [Aracs.Utilities.Jobs].SessionDestroyer As';
- Go
- Alter Procedure [Aracs.Utilities.Jobs].SessionDestroyer
- As
- Declare @JobHex NVarChar(32)
- ,@JobId UniqueIdentifier
- ;
- Select @JobHex = Substring(Program_Name, 32, 32)
- From sys.dm_Exec_Sessions
- Where Session_Id = @@Spid;
- Delete [Aracs.Utilities.Jobs].SessionSaverStore
- Where JobId = Cast('' as xml).value('xs:hexBinary(sql:variable("@JobHex") )', 'VarBinary(MAX)');
Along comes the SessionSaverStore next:
- If Object_Id('[Aracs.Utilities.Jobs].SessionSaverStore') Is Null
- Create Table [Aracs.Utilities.Jobs].SessionSaverStore
- (
- JobId UniqueIdentifier
- ,ParameterName NVarChar(128)
- ,Value Sql_Variant
- );
- If Object_Id('[Aracs.Utilities.Jobs].SessionSaver') Is Null
- Exec sp_ExecuteSql N'Create Procedure [Aracs.Utilities.Jobs].SessionSaver As';
- Go
- Alter Procedure [Aracs.Utilities.Jobs].SessionSaver
- @ParameterName NVarChar(128)
- ,@Value Sql_Variant
- ,@StartFresh Bit = 0
- As
- Declare @JobHex NVarChar(32)
- ,@JobId UniqueIdentifier
- ;
- Select @JobHex = Substring(Program_Name, 32, 32)
- From sys.dm_Exec_Sessions
- Where Session_Id = @@Spid;
- Set @JobId = Cast('' as xml).value('xs:hexBinary(sql:variable("@JobHex") )', 'VarBinary(MAX)');
- If Exists ( Select 1 From MSDB.dbo.sysJobs Where Job_Id = @JobId )
- Begin
- If @StartFresh = 1
- Exec [Aracs.Utilities.Jobs].SessionDestroyer;
- If Exists (
- Select 1
- From [Aracs.Utilities.Jobs].SessionSaverStore
- Where JobId = @JobId
- And ParameterName = @ParameterName
- )
- Update [Aracs.Utilities.Jobs].SessionSaverStore
- Set Value = @Value
- Where JobId = @JobId
- And ParameterName = @ParameterName;
- Else
- Insert
- Into [Aracs.Utilities.Jobs].SessionSaverStore
- (
- JobId
- ,ParameterName
- ,Value
- )
- Values
- (
- @JobId
- ,@ParameterName
- ,@Value
- );
- End
Finally the SessionRetriever:
- If Object_Id('[Aracs.Utilities.Jobs].SessionRetriever') Is Null
- Exec sp_ExecuteSql N'Create Procedure [Aracs.Utilities.Jobs].SessionRetriever As';
- Go
- Alter Procedure [Aracs.Utilities.Jobs].SessionRetriever
- @ParameterName NVarChar(128)
- ,@Value Sql_Variant Output
- As
- Declare @JobHex NVarChar(32)
- ,@JobId UniqueIdentifier
- ,@Valuei Sql_Variant
- ,@DataType NVarChar(128)
- ;
- Select @JobHex = Substring(Program_Name, 32, 32)
- From sys.dm_Exec_Sessions
- Where Session_Id = @@Spid;
- Set @JobId = Cast('' as xml).value('xs:hexBinary(sql:variable("@JobHex") )', 'VarBinary(MAX)');
- If Exists ( Select 1 From MSDB.dbo.sysJobs Where Job_Id = @JobId )
- Begin
- Select @Value = Value
- From [Aracs.Utilities.Jobs].SessionSaverStore
- Where JobId = @JobId
- And ParameterName = @ParameterName;
- End
Use is pretty straightforward. As an Proof of concept I created a Sql Agent Job with two steps – Store’ and ‘Fetch’
Store contained the following:
- Exec [Aracs.Utilities.Jobs].SessionSaver 'Name', 'Fred', 1
- Exec [Aracs.Utilities.Jobs].SessionSaver 'Age', 37
And Fetch:
- Declare @Name Sql_Variant
- Declare @Age Sql_Variant
- Exec[Aracs.Utilities.Jobs].SessionRetriever 'Name', @Name Output;
- Exec[Aracs.Utilities.Jobs].SessionRetriever 'Age', @Age Output;
- Print Cast(@Name As VarChar(128)) + ' ' + Cast( @Age As VarChar(4));
Granted it’s missing some bells and whistles (like exception handling) and I’d wager I could stuff the Retriever in as a function. However as a first hit I was pretty chuffed with it!