This is just a quick note on getting NAS4Free (and FreeNAS) to run on the HP Proliant MicroServer N40L when all your SATA drives are 3TB or bigger. Make sure you disable the RAID controller in the BIOS by changing the setting from RAID to AHCI. Without changing it, almost all of the BSD and Debian distros choke just after the boot loader. Several recovery distros did just fine without this change, so go figure.
With that done, I am now booting NAS4Free from a 1GB microSD in a very small USB converter attached to the N40L's internal USB port. Boot time is around 20 seconds. I have a ZFS mirror going on a pair of 3TB WD Red drives and I am getting 90-100MB/sec transfers from my Win7 desktop on GigE.
I followed the directions at http://wiki.apache.org/couchdb/Installing_on_Ubuntu, but I still ran into a small bit of trouble. Here are a couple quick fixes if you're running into issues building couchdb from the source download.
# make # ... # ./mochifmt.erl:none: error in parse transform 'eunit_autoexport': {undef, # ... apt-get install erlang-eunit # /etc/init.d/couchdb start # * Starting database server couchdb # Apache CouchDB needs write permission on the PID file: /var/run/couchdb/couchdb.pid # [fail] chown -R couchdb: /var/run/couchdb # ./couchdb # {"init terminating in do_boot",{{badmatch,{error,{"no such file or directory","os_mon.app"}}},[{couch,start,0},{init,start_it,1},{init,start_em,1}]}} apt-get install erlang
Also, if you're pulling from github instead of the tar.gz from couchdb.org, you need to start by running ./bootstrap
to make the configure script.
Time to relax!
This is just to document a recent frustration I had with a batch file wrapping a call to the InfoZip unzip.exe. (Hint: ever define an UNZIP env. variable?)
C:\testbin>unzip -v UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spieler. Send bug reports using http://www.info-zip.org/zip-bug.html; see README for details. Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ; see ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites. Compiled with Microsoft C 13.10 (Visual C++ 7.1) for Windows 9x / Windows NT/2K/XP/2K3 (32-bit) on Apr 20 2009. UnZip special compilation options: ASM_CRC COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported) NTSD_EAS SET_DIR_ATTRIB TIMESTAMP UNIXBACKUP USE_EF_UT_TIME USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported) USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported) UNICODE_SUPPORT [wide-chars] (handle UTF-8 paths) MBCS-support (multibyte character support, MB_CUR_MAX = 1) LARGE_FILE_SUPPORT (large files over 2 GiB supported) ZIP64_SUPPORT (archives using Zip64 for large files supported) USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version 1.0.5, 10-Dec-2007) VMS_TEXT_CONV [decryption, version 2.11 of 05 Jan 2007] UnZip and ZipInfo environment options: UNZIP: [none] UNZIPOPT: [none] ZIPINFO: [none] ZIPINFOOPT: [none] C:\testbin>set UNZIP=c:\testbin\unzip.exe C:\testbin>unzip -v Archive: c:/testbin/unzip.exe End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. note: c:/testbin/unzip.exe may be a plain executable, not an archive unzip: cannot find zipfile directory in c:/testbin/unzip.exe, and cannot find c:/testbin/unzip.exe.zip, period.
unzip.exe will use the UNZIP environment variable as flags to every invocation. Notice that it shows up in the Version output? Turns out, this is a documented feature to allow you to define system-wide options to unzip, such as converting line endings.
In case you'd like to know more, here is the documentation: http://www.info-zip.org/mans/unzip.html#ENVIRONMENT%20OPTIONS
Hope this doesn't bite you like it did me.
Here are a few open letters to some people who share the name Jeremy Murray (there are quite a few of us) whose communications have somehow ended up with me:
Dear Jeremy Murray born in September of 1975,
A debt collection agency named PRC (Professional Recovery Services) has been calling for you. They have an interesting robo dialer that does a decent Text-to-Speech job on our name. Their message considers your staying on the phone as confirmation of your identity, which is new to me. Anyway, they'd like to talk to you. Their phone number is 800-991-5278. It is somewhat difficult to convince them that I am not you and that I do not have your social security number. They said they wouldn't call me again, but that hasn't worked so far.
Hope it turns out to be a case of mistaken identity for you, too.
-Jeremy
Dear Jeremy Murray from Canada who participates in a hockey league,
Pierrefonds, Quebec seems like a really cool place. You guys definitely love your hockey! It is also very nifty that you have a league but allow players to sub out as needed. It is interesting how often a team ends up being short players TONIGHT and needs to send a global e-mail out looking for players.
I am glad that the season is starting up again, and if I lived anywhere close by and knew how to skate better than a blind moose on a steep incline, I'd love to attend.
Thanks for keeping me posted, though!
-Jeremy
Dear civil engineer Jeremy Murray from Australia,
I believe that Canberra is supposed to be just starting to warm up. That means you will probably be pretty busy approving parking lots and building footers. I will say that the plans that your various clients have sent for your approval remind me of when I was working as a surveyor in High School - good memories.
Hope all is well with you. If anyone ever sends me your real e-mail, I'll be happy to forward these on to you instead of replying to the clients themselves.
-Jeremy
Dear Jeremy Murray who is looking for a job,
Hello. I hope the job search is going well.
I looked over your resume that one of your prospects sent out. They were asking for clarifications on your education. I directed them to call you by the phone number it contained - I assumed that number was not also incorrect like the e-mail address.
They seemed very nice and were still interested in contacting you, so I hope that worked out.
-Jeremy
Dear Jeremy Murray who bought stuff from BlockBuster,
Hello. I know that spam is a major concern, so when you signed up for BlockBuster Total Access, you probably used my e-mail address just because you didn't feel it was important to get any communications from them.
But it turns out, it might be worth your time! Seems they have special offers on movies pretty constantly. They also send over all the receipts of everything you purchase. (Robin Hood is a damn fine movie, almost any version - good pick.)
Since their customer service department cannot be convinced otherwise (by e-mail or phone), I'll keep on receiving these until you change your address.
Happy watching!
-Jeremy
Dear Jeremy Murray who is looking for car insurance (in Alabama, I think),
Hi. About a year ago, it looks like you were investigating new car insurance online pretty heavily. You probably didn't want any spam (I can appreciate that) so you used my e-mail address instead of your own (I don't especially appreciate that).
Turns out that on several of the sites you visited, you requested quotes with follow-up contact. This left multiple insurance agents very confused and a little crestfallen that I am not at all interested in their insurance quotes, automobile or otherwise. They keep trying though, even up to today. This one guy named BJ from Allstate was especially interested in your business, so I believe he looked you up locally after our phone conversation.
Hope you found a good deal after being so thorough.
-Jeremy
Dear Jeremy Murray the professional skateboarder,
You totally deserve to be higher in google pagerank than me. I've never been mistaken for you or received any of your correspondence.
All of my skateboarding knowledge is from Tony Hawk and Skate or Die games, but your videos are pretty sick. Best of luck with that.
-Jeremy
One of my tools needed to track if its parent process was a shell or not. I found it very difficult to find parent process ID (PID) info without traversing into p/invoke territory. I have no idea why the .NET Process type does not include the info - seems like an easy thing, to me.
Anyway, what followed was my first peek at PerformanceCounters - there is some crazy stuff in there.
Everything I could find related to PID in .NET either pointed to ntdll.dll calls or to PerformanceCounter. Avoiding the extern, I delved into the counters. First off, I had no idea what counters there were and all the accessors for them are by string for the counter name and its category. I also found out that some counters are singletons while other can have multiple instances.
I decided to write a quick script to dump them all.
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; namespace PidExamples { class PrintAllPerformanceCounters { static void Main(string[] args) { ProcessUtil.PrintCategories(); } public static void PrintCategories() { var categories = System.Diagnostics.PerformanceCounterCategory.GetCategories(); for (int i = 0; i < categories.Length; i++) { PrintCounters(categories[i].CategoryName); } } public static void PrintCounters(string categoryName) { var counters = new ArrayList(); var category = new PerformanceCounterCategory(categoryName); try { var instanceNames = category.GetInstanceNames(); if (instanceNames.Length == 0) { counters.AddRange(category.GetCounters()); } else { for (int i = 0; i < instanceNames.Length; i++) { counters.AddRange(category.GetCounters(instanceNames[i])); } } foreach (System.Diagnostics.PerformanceCounter counter in counters) { if (string.IsNullOrEmpty(counter.InstanceName)) { Console.WriteLine(categoryName + ": " + counter.CounterName); } else { Console.WriteLine(categoryName + ": " + counter.CounterName + " (" + counter.InstanceName + ")"); } } } catch (System.Exception) { Console.WriteLine(categoryName + ": ?"); } } } }
This produced 13401 lines when I ran it on my desktop - that's far more than I was expecting. There are counters dealing with each processor and disk, as well as all sorts of ones for programs - especially Visual Studio and related dev tools. These are also just the counters - you can query any of them to get the associated data.
Digging through the list I found the lines dealing with Process information.
Process PerformanceCounters (Win 7): % Privileged Time % Processor Time % User Time Creating Process ID Elapsed Time Handle Count ID Process IO Data Bytes/sec IO Data Operations/sec IO Other Bytes/sec IO Other Operations/sec IO Read Bytes/sec IO Read Operations/sec IO Write Bytes/sec IO Write Operations/sec Page Faults/sec Page File Bytes Page File Bytes Peak Pool Nonpaged Bytes Pool Paged Bytes Priority Base Private Bytes Thread Count Virtual Bytes Virtual Bytes Peak Working Set Working Set - Private Working Set Peak
Awesome - there's PID (ID Process
) and Parent PID (Creating Process ID
). So now we'll just grab performance counters for all the processes and make a quick dictionary of child PID to parent PID. We can then index into that dictionary with our PID (easily accessible from Process.GetCurrentProcess().Id
) to get our parent, or we can traverse the dictionary and make a process tree if needed.
using System; using System.Collections.Generic; using System.Diagnostics; namespace PidExamples { class ParentPid { static void Main(string[] args) { var childPidToParentPid = GetAllProcessParentPids(); int currentProcessId = Process.GetCurrentProcess().Id; Console.WriteLine("Current Process PID: " + currentProcessId); Console.WriteLine("Parent Process PID: " + childPidToParentPid[currentProcessId]); } public static Dictionary<int, int> GetAllProcessParentPids() { var childPidToParentPid = new Dictionary<int, int>(); var processCounters = new SortedDictionary<string, PerformanceCounter[]>(); var category = new PerformanceCounterCategory("Process"); // As the base system always has more than one process running, // don't special case a single instance return. var instanceNames = category.GetInstanceNames(); foreach(string t in instanceNames) { try { processCounters[t] = category.GetCounters(t); } catch (InvalidOperationException) { // Transient processes may no longer exist between // GetInstanceNames and when the counters are queried. } } foreach (var kvp in processCounters) { int childPid = -1; int parentPid = -1; foreach (var counter in kvp.Value) { if ("ID Process".CompareTo(counter.CounterName) == 0) { childPid = (int)(counter.NextValue()); } else if ("Creating Process ID".CompareTo(counter.CounterName) == 0) { parentPid = (int)(counter.NextValue()); } } if (childPid != -1 && parentPid != -1) { childPidToParentPid[childPid] = parentPid; } } return childPidToParentPid; } } }
Note that when we actually start querying, the counters for specific processes may no longer be available. The instance list was a snapshot, and the list is changing all the time, so we need to wrap our check on the specific instance to guard against errors if a process no longer exists. If you are only interested in the PID of the current process, you could speed this up quite a bit by checking for just instances with your executable name.
D:\>ParentPid.exe Current Process PID: 90820 Parent Process PID: 92712 D:\>ParentPid.exe Current Process PID: 92636 Parent Process PID: 92712
Well, the information is available. The number of performance counters is crazy to me - it really makes me wonder what kind of overhead goes into tracking and updating them.
In other news, the p/invoke method is much faster, cleaner, and better at tracking processes over time - I'd stick with that direction if you are really depending on this.