Permalink
Browse files

Initial Commit

  • Loading branch information...
0 parents commit f0a4f10dbfd0c0300e555d98fa6cc036b12a4b08 @bgreenlee committed Oct 22, 2012
@@ -0,0 +1,18 @@
+# Xcode
+.DS_Store
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+*.xcworkspace
+!default.xcworkspace
+xcuserdata
+profile
+*.moved-aside
+DerivedData
+.idea/

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,15 @@
+//
+// JTAppDelegate.h
+// JobTracker
+//
+// Created by Brad Greenlee on 10/21/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface JTAppDelegate : NSObject <NSApplicationDelegate>
+
+@property (assign) IBOutlet NSWindow *window;
+
+@end
@@ -0,0 +1,19 @@
+//
+// JTAppDelegate.m
+// JobTracker
+//
+// Created by Brad Greenlee on 10/21/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import "JTAppDelegate.h"
+
+@implementation JTAppDelegate
+@synthesize window;
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
+{
+
+}
+
+@end
@@ -0,0 +1,44 @@
+//
+// JTJob.h
+// JobTracker
+//
+// Created by Brad Greenlee on 11/9/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface JTJob : NSObject {
+ NSDictionary *jobData;
+}
+
+@property (nonatomic, copy) NSString *jobId;
+@property (nonatomic, copy) NSString *priority;
+@property (nonatomic, copy) NSString *user;
+@property (nonatomic, copy) NSString *name;
+@property (nonatomic, copy) NSString *displayName;
+@property (nonatomic, copy) NSString *mapPctComplete;
+@property (nonatomic, copy) NSString *mapTotal;
+@property (nonatomic, copy) NSString *mapsCompleted;
+@property (nonatomic, copy) NSString *reducePctComplete;
+@property (nonatomic, copy) NSString *reduceTotal;
+@property (nonatomic, copy) NSString *reducesComplete;
+@property (nonatomic, copy) NSString *jobSchedulingInfo;
+@property (nonatomic, copy) NSString *diagnosticInfo;
+
+- (id)initWithDictionary:(NSDictionary *)dict;
+- (NSString *)jobId;
+- (NSString *)priority;
+- (NSString *)user;
+- (NSString *)name;
+- (NSString *)displayName;
+- (NSString *)mapPctComplete;
+- (NSString *)mapTotal;
+- (NSString *)mapsCompleted;
+- (NSString *)reducePctComplete;
+- (NSString *)reduceTotal;
+- (NSString *)reducesComplete;
+- (NSString *)jobSchedulingInfo;
+- (NSString *)diagnosticInfo;
+
+@end
@@ -0,0 +1,76 @@
+//
+// JTJob.m
+// JobTracker
+//
+// Created by Brad Greenlee on 11/9/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import "JTJob.h"
+
+@implementation JTJob
+
+@synthesize jobId, priority, user, name, displayName, mapPctComplete, mapTotal, mapsCompleted,
+reducePctComplete, reduceTotal, reducesComplete, jobSchedulingInfo, diagnosticInfo;
+
+- (id)initWithDictionary:(NSDictionary *)dict {
+ if ((self = [super init])) {
+ jobData = dict;
+ }
+ return self;
+}
+
+- (NSString *)jobId {
+ return [jobData objectForKey:@"job_id"];
+}
+
+- (NSString *)priority {
+ return [jobData objectForKey:@"priority"];
+}
+
+- (NSString *)user {
+ return [jobData objectForKey:@"user"];
+}
+
+- (NSString *)name {
+ return [jobData objectForKey:@"name"];
+}
+
+- (NSString *)displayName {
+ NSArray *parts = [self.name componentsSeparatedByString:@" "];
+ return [NSString stringWithFormat:@"%@ (%@)", [parts objectAtIndex:[parts count]-1], self.user];
+}
+
+- (NSString *)mapPctComplete {
+ return [jobData objectForKey:@"map_pct_complete"];
+}
+
+- (NSString *)mapTotal {
+ return [jobData objectForKey:@"map_total"];
+}
+
+- (NSString *)mapsCompleted {
+ return [jobData objectForKey:@"maps_completed"];
+}
+
+- (NSString *)reducePctComplete {
+ return [jobData objectForKey:@"reduce_pct_complete"];
+}
+
+- (NSString *)reduceTotal {
+ return [jobData objectForKey:@"reduce_total"];
+}
+
+- (NSString *)reducesComplete {
+ return [jobData objectForKey:@"reduces_complete"];
+}
+
+- (NSString *)jobSchedulingInfo {
+ return [jobData objectForKey:@"job_scheduling_info"];
+}
+
+- (NSString *)diagnosticInfo {
+ return [jobData objectForKey:@"diagnostic_info"];
+}
+
+@end
@@ -0,0 +1,24 @@
+//
+// JTParser.h
+// JobTracker
+//
+// Created by Brad Greenlee on 11/6/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "JTJob.h"
+
+#define JT_URL @"http://jobtracker.doop.ny4.etsy.com:50030/jobtracker.jsp"
+
+@interface JTState : NSObject {
+ NSMutableDictionary *clusterSummary;
+ NSMutableDictionary *jobs;
+}
+
+@property(nonatomic, retain) NSMutableDictionary *clusterSummary;
+@property(nonatomic, retain) NSMutableDictionary *jobs;
+
+- (void)refresh;
+- (void)parse:(NSXMLDocument *)document;
+@end
@@ -0,0 +1,86 @@
+//
+// JTParser.m
+// JobTracker
+//
+// Created by Brad Greenlee on 11/6/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import "JTState.h"
+
+@implementation JTState
+
+@synthesize clusterSummary, jobs;
+
+- (id)init {
+ if ((self = [super init])) {
+ clusterSummary = [[NSMutableDictionary alloc] init];
+ jobs = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (void)refresh {
+ NSError *err;
+ NSXMLDocument *document = [[NSXMLDocument alloc] initWithContentsOfURL:[NSURL URLWithString:JT_URL]
+ options:NSXMLDocumentTidyHTML error:&err];
+
+// NSString *filePath = [[NSBundle mainBundle] pathForResource:@"jt_sample" ofType:@"html"];
+// NSData *data = [NSData dataWithContentsOfFile:filePath];
+// NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:NSXMLDocumentTidyHTML error:nil];
+
+ if (err) {
+ NSLog(@"ERROR: %@", err);
+ }
+
+ if (document) {
+ [self parse:document];
+ }
+}
+
+- (void)parse:(NSXMLDocument *)document {
+ // Cluster Summary
+ NSArray *nodes = [document nodesForXPath:@".//table[1]" error:nil];
+ NSXMLElement *clusterSummaryTable;
+ if ([nodes count] > 0) {
+ clusterSummaryTable = [nodes objectAtIndex:0];
+ nodes = [clusterSummaryTable nodesForXPath:@"./tr[2]//td" error:nil];
+ if ([nodes count] > 0) {
+ NSArray *attribs = [NSArray arrayWithObjects:@"running_map_tasks", @"running_reduce_tasks", @"total_submissions",
+ @"nodes", @"occupied_map_slots", @"occupied_reduce_slots", @"reserved_map_slots",
+ @"reserved_reduce_slots", @"map_task_capacity", @"reduce_task_capacity", @"avg_tasks_per_node",
+ @"blacklisted_nodes", @"excluded_nodes", nil];
+ [attribs enumerateObjectsUsingBlock:^(id attrib, NSUInteger idx, BOOL *stop) {
+ NSString *value = [[[nodes objectAtIndex:idx] stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ [clusterSummary setObject:value forKey:attrib];
+ }];
+ }
+ }
+
+ NSLog(@"cluster summary: %@", clusterSummary);
+
+ // Jobs tables
+ NSArray *dataTables = [document nodesForXPath:@".//table[@class='datatable']" error:nil];
+ NSArray *jobTypes = [NSArray arrayWithObjects:@"running", @"completed", @"failed", nil];
+ [jobTypes enumerateObjectsUsingBlock:^(id jobType, NSUInteger idx, BOOL *stop) {
+ NSXMLElement *jobsTable = [dataTables objectAtIndex:idx];
+ NSArray *jobRows = [jobsTable nodesForXPath:@"./tbody/tr" error:nil];
+ NSMutableArray *jobList = [[NSMutableArray alloc] init];
+ for (NSXMLElement *jobRow in jobRows) {
+ NSArray *jobCells = [jobRow nodesForXPath:@"./td" error:nil];
+ NSArray *attribs = [NSArray arrayWithObjects:@"job_id", @"priority", @"user", @"name", @"map_pct_complete",
+ @"map_total", @"maps_completed", @"reduce_pct_complete", @"reduce_total", @"reduces_complete",
+ @"job_scheduling_info", @"diagnostic_info", nil];
+ NSMutableDictionary *jobData = [[NSMutableDictionary alloc] init];
+ [attribs enumerateObjectsUsingBlock:^(id attrib, NSUInteger idx, BOOL *stop) {
+ NSString *value = [[[jobCells objectAtIndex:idx] stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ [jobData setObject:value forKey:attrib];
+ }];
+ [jobList addObject:[[JTJob alloc] initWithDictionary:jobData]];
+ }
+ [jobs setObject:jobList forKey:jobType];
+ }];
+
+ NSLog(@"jobs: %@", jobs);
+}
+@end
@@ -0,0 +1,31 @@
+//
+// JTStatusMenu.h
+// JobTracker
+//
+// Created by Brad Greenlee on 10/21/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "JTState.h"
+#import "JTJob.h"
+
+#define RUNNING_JOBS_TAG 1
+#define COMPLETED_JOBS_TAG 2
+#define FAILED_JOBS_TAG 3
+
+@interface JTStatusMenu : NSObject {
+ IBOutlet NSMenu *statusMenu;
+ NSStatusItem *statusItem;
+ NSImage *statusImage;
+ NSImage *statusHighlightImage;
+ NSImage *statusDisabledHighlightImage;
+ JTState *jtState;
+}
+
+- (IBAction)refresh:(id)sender;
+- (IBAction)openInBrowser:(id)sender;
+- (void)updateMenuItemWithTag:(NSInteger)tag withJobs:(NSArray *)jobs;
+- (void)jobSelected:(id)sender;
+
+@end
@@ -0,0 +1,73 @@
+//
+// JTStatusMenu.m
+// JobTracker
+//
+// Created by Brad Greenlee on 10/21/12.
+// Copyright (c) 2012 Hack Arts. All rights reserved.
+//
+
+#import "JTStatusMenu.h"
+#import "JTState.h"
+
+@implementation JTStatusMenu
+
+- (void)awakeFromNib {
+ statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
+ statusImage = [NSImage imageNamed:@"elephant_icon_big_black.png"];
+ statusHighlightImage = [NSImage imageNamed:@"elephant_icon_big_white.png"];
+ [statusItem setImage:statusImage];
+ [statusItem setAlternateImage:statusHighlightImage];
+ [statusItem setHighlightMode:YES];
+ [statusMenu setAutoenablesItems:NO];
+ [statusItem setMenu:statusMenu];
+
+ // Listen for events when the computer wakes from sleep, which otherwise
+ // throws off the refresh schedule.
+ [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
+ selector:@selector(receiveWakeNote:)
+ name:NSWorkspaceDidWakeNotification
+ object:nil];
+
+ if (jtState == nil) {
+ jtState = [[JTState alloc] init];
+ }
+ [self refresh:self];
+}
+
+- (IBAction)refresh:(id)sender {
+ [jtState refresh];
+ [self updateMenuItemWithTag:RUNNING_JOBS_TAG withJobs:[jtState.jobs objectForKey:@"running"]];
+ [self updateMenuItemWithTag:COMPLETED_JOBS_TAG withJobs:[jtState.jobs objectForKey:@"completed"]];
+ [self updateMenuItemWithTag:FAILED_JOBS_TAG withJobs:[jtState.jobs objectForKey:@"failed"]];
+}
+
+- (IBAction)openInBrowser:(id)sender {
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:JT_URL]];
+}
+
+- (void)updateMenuItemWithTag:(NSInteger)tag withJobs:(NSArray *)jobs {
+ NSMenu *jobsMenu = [[NSMenu alloc] init];
+ NSMenuItem *jobsMenuItem = [statusMenu itemWithTag:tag];
+ if ([jobs count] == 0) {
+ NSMenuItem *noneItem = [[NSMenuItem alloc] initWithTitle:@"None" action:nil keyEquivalent:@""];
+ [noneItem setEnabled:NO];
+ [jobsMenu addItem:noneItem];
+ } else {
+ for (JTJob *job in jobs) {
+ NSMenuItem *jobItem = [[NSMenuItem alloc] initWithTitle:job.displayName action:@selector(jobSelected:) keyEquivalent:@""];
+ [jobItem setRepresentedObject:job];
+ [jobItem setTarget:self];
+ [jobItem setEnabled:YES];
+ [jobsMenu addItem:jobItem];
+ }
+ }
+ [statusMenu setSubmenu:jobsMenu forItem:jobsMenuItem];
+}
+
+- (void)jobSelected:(id)sender {
+ NSMenuItem *menuItem = sender;
+ JTJob *job = [menuItem representedObject];
+ NSString *jobUrl = [NSString stringWithFormat:@"%@?job_id=%@", JT_URL, job.jobId];
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:jobUrl]];
+}
+@end
Oops, something went wrong.

0 comments on commit f0a4f10

Please sign in to comment.