From 49fcefbf2d1ba18650507fc3753d123034b90243 Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Sat, 14 Dec 2013 15:37:09 +0100 Subject: [PATCH] Various cleanings & minor fix (xapi.js). --- src/MappedCollection.coffee | 54 ++++++++++++++++++------------------- src/fibers-utils.coffee | 19 +++++++++++-- src/main.coffee | 3 --- src/spec.coffee | 5 +++- src/xapi.coffee | 32 +++++++++------------- src/xo.coffee | 40 ++++++++++++--------------- 6 files changed, 78 insertions(+), 75 deletions(-) diff --git a/src/MappedCollection.coffee b/src/MappedCollection.coffee index 30281cf5b..8712752f8 100644 --- a/src/MappedCollection.coffee +++ b/src/MappedCollection.coffee @@ -1,27 +1,28 @@ +# Low level tools. $_ = require 'underscore' -###################################################################### +#===================================================================== -class DynamicProperty +class $DynamicProperty constructor: (@value, @hooks) -> -#--------------------------------------------------------------------- +#===================================================================== -noop = -> +$noop = -> -copyDeep = (value) -> +$copyDeep = (value) -> if value instanceof Array - return (copyDeep item for item in value) + return ($copyDeep item for item in value) if value instanceof Object result = {} - result[key] = copyDeep item for key, item of value + result[key] = $copyDeep item for key, item of value return result return value -getDeep = (obj, path) -> +$getDeep = (obj, path) -> return obj if path.length is 0 current = obj @@ -34,7 +35,7 @@ getDeep = (obj, path) -> current[path[i]] -setDeep = (obj, path, value) -> +$setDeep = (obj, path, value) -> throw new Error 'invalid path' if path.length is 0 current = obj @@ -50,7 +51,7 @@ setDeep = (obj, path, value) -> # @param rule Rule of the current item. # @param item Current item. # @param value Value of the generator item. -computeValue = (rule, item, value) -> +$computeValue = (rule, item, value) -> # @param parent The parent object of this entry (necessary for # assignment). @@ -61,8 +62,8 @@ computeValue = (rule, item, value) -> helper = (parent, name, spec) -> if not $_.isObject spec parent[name] = spec - else if spec instanceof DynamicProperty - # If there was no previous value use DynamicProperty.value, + else if spec instanceof $DynamicProperty + # If there was no previous value use $DynamicProperty.value, # otherwise, just keep the previous value. if parent[name] is undefined # Helper is re-called for the initial value. @@ -85,7 +86,7 @@ computeValue = (rule, item, value) -> ###################################################################### -class MappedCollection +class $MappedCollection constructor: (spec) -> @@ -94,8 +95,8 @@ class MappedCollection if $_.isFunction spec ctx = dynamic: (initialValue, hooks) -> - new DynamicProperty initialValue, hooks - noop: noop + new $DynamicProperty initialValue, hooks + noop: $noop spec = spec.call ctx @@ -114,7 +115,7 @@ class MappedCollection spec.rules or= {} - # Rules are the core of MappedCollection, they allow to categorize + # Rules are the core of $MappedCollection, they allow to categorize # objects and to treat them differently. @_rules = {} @@ -198,7 +199,7 @@ class MappedCollection # If the value is a dynamic property, grabs the initial value # and registers its hooks. - if value instanceof DynamicProperty + if value instanceof $DynamicProperty hooks = value.hooks # Browse hooks for each rules. @@ -220,7 +221,7 @@ class MappedCollection # current rule. for key, item of items # Value of the current field. - field = getDeep item.value, path + field = $getDeep item.value, path ctx = {rule, field} ctx.__proto__ = item # Links to the current item. @@ -228,7 +229,7 @@ class MappedCollection hook.call ctx, value, key # Updates the value if it changed. - setDeep item.value, path if ctx.field isnt field + $setDeep item.value, path if ctx.field isnt field # Checks each hook is correctly defined. {enter, update, exit} = hooks_ @@ -273,7 +274,7 @@ class MappedCollection value: undefined # Computes the value. - computeValue rule, item + $computeValue rule, item # No events for static items. @@ -306,11 +307,10 @@ class MappedCollection # Adds, updates or removes items from the collections. Items not # present are added, present are updated, and present in the # generated collection but not in the generator are removed. - set: (items, options = {}) -> - {add, update, remove} = options + set: (items, {add, update, remove} = {}) -> add = true if add is undefined update = true if update is undefined - remove = true if remove is undefined + remove = false if remove is undefined itemsToRemove = {} if remove @@ -329,7 +329,7 @@ class MappedCollection rule = @_rules[item._ruleName] # Compute the new value. - computeValue rule, item, value + $computeValue rule, item, value # Runs related hooks. for hook in @_hooks[rule.name]?.update or [] @@ -351,7 +351,7 @@ class MappedCollection value: undefined # Computes the value. - computeValue rule, item, value + $computeValue rule, item, value # Runs related hooks. for hook in @_hooks[rule.name]?.enter or [] @@ -369,6 +369,6 @@ class MappedCollection # Removes effectively the item. delete @_byKey[key] @_byRule[ruleName][key] -###################################################################### +#===================================================================== -module.exports = MappedCollection +module.exports = $MappedCollection diff --git a/src/fibers-utils.coffee b/src/fibers-utils.coffee index 6adc07ede..2b67e6682 100644 --- a/src/fibers-utils.coffee +++ b/src/fibers-utils.coffee @@ -1,3 +1,6 @@ +# Low level tools. +$_ = require 'underscore' + # Async code is easier with fibers (light threads)! $fiber = require 'fibers' @@ -8,15 +11,26 @@ $fiberize = (fn) -> (args...) -> $fiber(-> fn args...).run() +# Makes the fiber waits for a number of miliseconds. +$sleep = (ms) -> + fiber = $fiber.current + setTimeout (-> fiber.run()), ms + $fiber.yield() + # Makes an asynchrouneous function synchrouneous (in a fiber). -$synchronize = (fn) -> +$synchronize = (fn, ctx) -> + fn = ctx[fn] if $_.isString fn + (args...) -> fiber = $fiber.current - fn args..., (error, result) -> + + args.push (error, result) -> if error? fiber.throwInto error else fiber.run result + fn.apply ctx, args + $fiber.yield() # TODO: remove promises ASAP. @@ -32,6 +46,7 @@ $waitForPromise = (promise) -> module.exports = { $fiberize + $sleep $synchronize $waitForPromise } diff --git a/src/main.coffee b/src/main.coffee index 105b059cf..8b112ede4 100644 --- a/src/main.coffee +++ b/src/main.coffee @@ -13,9 +13,6 @@ $_ = require 'underscore' # HTTP(s) middleware framework. $connect = require 'connect' -# Async code is easier with fibers (light threads)! -$fiber = require 'fibers' - # Configuration handling. $nconf = require 'nconf' diff --git a/src/spec.coffee b/src/spec.coffee index 4f252c22d..d6a9c46dc 100644 --- a/src/spec.coffee +++ b/src/spec.coffee @@ -199,7 +199,10 @@ module.exports = (refsToUUIDs) -> iSCSI_name: (value) -> value.other_config?.iscsi_iqn - memory: {} # TODO + memory: { # TODO + usage: 0 + size: 0 + } power_state: 'Running' # TODO diff --git a/src/xapi.coffee b/src/xapi.coffee index 02674f757..3c2ca5634 100644 --- a/src/xapi.coffee +++ b/src/xapi.coffee @@ -1,20 +1,13 @@ -# Async code is easier with fibers (light threads) and futures! -Fiber = require 'fibers' -Future = require 'fibers/future' +$xmlrpc = require 'xmlrpc' -xmlrpc = require 'xmlrpc' +#--------------------------------------------------------------------- + +# Helpers for dealing with fibers. +{$sleep, $synchronize} = require './fibers-utils' #===================================================================== -sleep = (ms) -> - fiber = Fiber.current; - setTimeout (-> fiber.run()), ms - Fiber.yield() - -#===================================================================== - -# Note: All methods are synchroneous (using fibers), `.future()` may -# be used to make them asynchroneous. +# Note: All methods are synchroneous (using fibers). class XAPI constructor: ({@host, @username, @password}) -> @@ -28,12 +21,16 @@ class XAPI # Makes sure there is not session id left. delete @sessionId - @xmlrpc = xmlrpc.createSecureClient { + @xmlrpc = $xmlrpc.createSecureClient { hostname: @host port: '443' rejectUnauthorized: false } + # Make `methodCall()` synchroneous. + @xmlrpc.methodCall = $synchronize 'methodCall', @xmlrpc + + # Logs in. @logIn() call: (method, args...) -> @@ -42,11 +39,8 @@ class XAPI args.unshift @sessionId if @sessionId do helper = => - future = new Future() - @xmlrpc.methodCall method, args, future.resolver() - try - result = future.wait() + result = @xmlrpc.methodCall method, args # Returns the plain result if it does not have a valid XAPI format. return result unless result.Status? @@ -80,7 +74,7 @@ class XAPI # I would like to be able to use a shorter delay but for some # reason, when we connect to XAPI at a give moment, the # connection hangs. - Fiber.sleep(500) + $sleep 500 helper() # XAPI is sometimes reinitialized and sessions are lost. diff --git a/src/xo.coffee b/src/xo.coffee index 0604e6d0d..e77605f80 100644 --- a/src/xo.coffee +++ b/src/xo.coffee @@ -9,9 +9,6 @@ $_ = require 'underscore' # Password hasing. $hashy = require 'hashy' -# Async code is easier with fibers (light threads)! -$fiber = require 'fibers' - # Redis. $createRedisClient = (require 'then-redis').createClient @@ -21,9 +18,6 @@ $createRedisClient = (require 'then-redis').createClient # specification. $MappedCollection = require './MappedCollection' -# Collection where models are stored in memory. -$MemoryCollection = require './collection/memory' - # Collection where models are stored in a Redis DB. $RedisCollection = require './collection/redis' @@ -38,34 +32,34 @@ $XAPI = require './xapi' #===================================================================== -$randomBytes = $synchronize $crypto.randomBytes +$randomBytes = $synchronize 'randomBytes', $crypto #===================================================================== # Models and collections. -class Server extends $Model +class $Server extends $Model validate: -> # TODO -class Servers extends $RedisCollection - model: Server +class $Servers extends $RedisCollection + model: $Server #--------------------------------------------------------------------- -class Token extends $Model +class $Token extends $Model @generate: (userId) -> - new Token { + new $Token { id: ($randomBytes 32).toString 'base64' user_id: userId } validate: -> # TODO -class Tokens extends $RedisCollection - model: Token +class $Tokens extends $RedisCollection + model: $Token #--------------------------------------------------------------------- -class User extends $Model +class $User extends $Model default: { permission: 'none' } @@ -97,11 +91,11 @@ class User extends $Model perms[@get 'permission'] => perms[permission] -class Users extends $RedisCollection - model: User +class $Users extends $RedisCollection + model: $User create: (email, password, permission) -> - user = new User { + user = new $User { email: email } user.setPassword password @@ -111,24 +105,24 @@ class Users extends $RedisCollection #===================================================================== -class XO +class $XO start: (config) -> # Connects to Redis. redis = $createRedisClient config.redis.uri # Creates persistent collections. - @servers = new Servers { + @servers = new $Servers { connection: redis prefix: 'xo:server' indexes: ['host'] } - @tokens = new Tokens { + @tokens = new $Tokens { connection: redis prefix: 'xo:token' indexes: ['host'] } - @users = new Users { + @users = new $Users { connection: redis prefix: 'xo:user' indexes: ['host'] @@ -277,4 +271,4 @@ class XO #===================================================================== -module.exports = XO +module.exports = $XO