Programming FSRM quotas

Introduction

Recently I was evaluating the options I had for implementing disk quotas on a backend system running on a major Internet Service Provider in Brazil.

Windows offers quota management up to some degree since NTFS 5 (Windows 2000) with user/volume quotas. Those were not appropriate for our scenario since we needed to set quotas on a per directory basis and this was not supported natively by Windows until the arrival of Windows Server 2003 R2.

R2 brings us a new feature called File Server Resource Manager a.k.a. FSRM. It is exposed for the system administrator as an MMC 3.0 snap-in.

Unfortunately, as of today Microsoft does not officially support any way for programming against FSRM quotas.  I said “officially support” because if the snap-in can do it, probably we can too! So after some research I found two DLLs called srm.dll and srmlib.dll that happens to do the stuff we want. Srm.dll exposes FSRM functionality through COM and srmlib.dll is a managed code wrapper around srm.dll.

Let’s take a look at some sample code:

using System;

using System.Collections.Generic;

using System.Text;

using Microsoft.Storage;

using System.IO;

using System.Runtime.InteropServices;

 

namespace Fsrm {

    class Program {

        static void Main(string[] args) {

            string directoryName = @"c:FsrmTests";

 

            // Creates a directory for testing if necessary

            if (!Directory.Exists(directoryName)) {

                Directory.CreateDirectory(directoryName);

            }

           

            ISrmQuotaManager quotaManager = new SrmQuotaManagerClass();

            ISrmQuota quota = null;

            try {

                // Try to get quota info

                quota = quotaManager.GetQuota(directoryName);

                quota.QuotaLimit *= 2;

            }

            catch (COMException ex) {

                unchecked {

                    if (ex.ErrorCode == (int)0x80045301) {

                        // Quota doesn’t exist for this directory. Create it.

                        Console.WriteLine("No quota defined for ‘{0}’. Creating quota.", directoryName);

                        quota = quotaManager.CreateQuota(directoryName);

                        quota.QuotaLimit = 1024 * 1024;

                    }

                    else {

                        Console.WriteLine(ex);

                        return;

                    }

                }

            }

 

            // Update quota info

            quota.Commit();

 

            // Add new file to the diretory to see QuotaUsed getting updated

            File.WriteAllText(directoryName + @"" + Path.GetRandomFileName() + ".txt", "Testing FSRM directory quotas");

            Console.WriteLine("New file added. Quota doubledrn{0} of {1} used.", quota.QuotaUsed, quota.QuotaLimit);

        }

    }

}

 

This sample doubles the size of the directory’s quota and puts a file in it every time it is run.

There are a bunch of other classes and methods available. Have fun!

Certification Update

This week I passed another couple of exams:

70-551 – UPGRADE: MCAD Skills to MCPD Web Developer by Using the Microsoft® .NET Framework

70-300 – Analyzing Requirements and Defining Microsoft .NET Solution Architectures

With 70-551 I became an MCPD Web Developer and as a side effect, an MCTS .NET Framework 2.0 Web Applications

 

Yesss!

Dependency Hell – Or Compilation-time DLL Hell

For the last couple of months I’ve been working on a project on which the entire Visual Studio solution has 65 projects.

Luckily I’ve been able to work with a smaller solution with only a subset of the projects: The ones that I was working directly with and the ones that I needed for a reason or another.

Unfortunately a couple of weeks ago, the time to start integrating my projects to the main solution arrived and since then I and other team members have been having troubles setting up references between projects.

I ended up detecting that the problems where caused by the references being set by file when for the sake of easy compilation they should been referenced by project.

I then reviewed all the projects setting their reference types to project references and the number of issues fell dramatically.

But occasionally a team member was getting compilation errors during to version number conflicts.

Imagine that project A depends on projects B and C and that B and C depend on different versions of D.

When you try to build the entire solution, although references where set to projects instead of files, Visual Studio 2003 couldn’t compile project A stating that there where conflicting versions of D in the bin folder.

Well, to get the story short, after trying to get rid of the error I searched around and ended up finding an article the explained how to resolve the issue: Error: the dependency ‘file’ in project ‘project’ cannot be copied to the run directory because it would conflict with dependency ‘file’  

 

This thing still has some bugs

It looks like my plans on becoming a multi-billionaire referring links to Amazon have failed. 😛

Today I tried to include another book on my list, but the site simply started to generate wrong URLs.

Another bug that bothers me is the fact from time to time the lists don’t render correctly:

Let’s hope these bugs are fixed as soon as possible.

What do you do with the books you don’t want anymore?

I have lots of books. I buy lots of them, but I don’t want to keep all of them.
Some have already done their job – as the ones I bought to study towards certification. Others are simply bad books.
What do you do with the books you don’t want anymore?
Keep them anyway? Give them away? Sell them? How do you sell them?

Global.asax event handling internals (part 1 of 3)

Some days ago I and another project member were seeing the best way to catch unhandled exceptions in ASP.NET.
We found the Global.Application_Error method in Global.asax which them.
Besides Application_Error, Visual Studio creates some other methods for handling events in Global.asax:
 
protected void Application_Start(Object sender, EventArgs e)
{
}
protected void Session_Start(Object sender, EventArgs e)
{
}
protected void Application_BeginRequest(Object sender, EventArgs e)
{
}
protected void Application_EndRequest(Object sender, EventArgs e)
{
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
}
protected void Application_Error(Object sender, EventArgs e)
{
}
protected void Session_End(Object sender, EventArgs e)
{
}
protected void Application_End(Object sender, EventArgs e)
{
}
 
All the methods have a signature compatible with the EventHandler delegate but none of the events are declared in Global or HttpAppliaction.
So how are the methods bound to the events?
If you ask it to Doug Purdy (the Remoting’s father e one of the fathers of Indigo), he would probably answer that it is magic as he did when answering a question of mine about Remoting. But I (whom am not the father of Indigo or Remoting and started studying ASP.NET a couple of weeks ago) will answer:
It does the binding during application initialization using a lot of Reflection.
Handed with my debugger (Visual Studio) and .NET Reflector, I found an internal class called HttpApplicationFactory which is who initializes the application.
But before instantiating an object from Global (in fact a class derived from Global created automatically), HttpApplicationFactory enumerates all Global’s methods within the ReflectOnApplicationType method and with ReflectOnMethodInfoIfItLooksLikeEventHandler() inserts every method that has as name that looks like an event handler in a list.
This list will be enumerated by HttpApplicaton. HookupEventHandlersForAppplicationAndModules to find events whose name is “compatible” with the methods found in Global.
When a compatible name is found, Reflection is used again to bind the method to the event.
As a piece of code worth more than “ new Regex(@"((w+)s)*").Matches(milPalavras).Count” words, follow to the next post.
 
PS.: This is due to the fact that MSN Spaces has a limit on the post’s sizes.

Databinding: Web Forms vs. Windows Forms

In Windows Forms, all data binding done by the designer is saved as code in the choosen language: C# or VB.NET:

 

//

// dataGrid1

//

this.dataGrid1.DataMember = "Customers";

this.dataGrid1.DataSource = this.dataSet11;

 

On Web Forms, it’s somewhat different, because when binding a DataGrid to a DataTable via designer, the binding isn’t saved as code; instead it’s saved as markup:

 

<asp:DataGrid id=DataGrid1 style="Z-INDEX: 101; LEFT: 16px; POSITION: absolute; TOP: 32px" runat="server" DataSource="<%# dataSet11 %>" DataKeyField="CustomerID" DataMember="Customers" AutoGenerateColumns="False" EnableViewState="False">

      // Column definition

</asp:DataGrid>