ia64/xen-unstable
changeset 1687:d7fd2dca5e0a
bitkeeper revision 1.1041.1.13 (40eae0ff9eEfOSJXwKN6Yf4HBbnbGg)
Merge ssh://xenbk@gandalf//var/bk/djm/xeno-unstable-common.bk
into kirby.fc.hp.com:/home/djm/src/xen/xeno-unstable-common.bk
Merge ssh://xenbk@gandalf//var/bk/djm/xeno-unstable-common.bk
into kirby.fc.hp.com:/home/djm/src/xen/xeno-unstable-common.bk
line diff
1.1 --- a/.rootkeys Tue Jul 06 17:25:40 2004 +0000 1.2 +++ b/.rootkeys Tue Jul 06 17:27:27 2004 +0000 1.3 @@ -201,6 +201,8 @@ 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/mis 1.4 3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README 1.5 3f6dc142IHaf6XIcAYGmhV9nNSIHFQ tools/misc/miniterm/miniterm.c 1.6 40c9c469kT0H9COWzA4XzPBjWK0WsA tools/misc/netfix 1.7 +4022a73cEKvrYe_DVZW2JlAxobg9wg tools/misc/nsplitd/Makefile 1.8 +4022a73cKms4Oq030x2JBzUB426lAQ tools/misc/nsplitd/nsplitd.c 1.9 3f870808_8aFBAcZbWiWGdgrGQyIEw tools/misc/p4perf.h 1.10 3f5ef5a2ir1kVAthS14Dc5QIRCEFWg tools/misc/xen-clone 1.11 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README 1.12 @@ -239,6 +241,7 @@ 40c9c4686jruMyZIqiaZRMiMoqMJtg tools/pyt 1.13 40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/python/xen/xend/XendVnet.py 1.14 40c9c468x191zetrVlMnExfsQWHxIQ tools/python/xen/xend/__init__.py 1.15 40c9c468S2YnCEKmk4ey8XQIST7INg tools/python/xen/xend/encode.py 1.16 +40e9808elkoRulOo1GxRTp5ulJGVNw tools/python/xen/xend/packing.py 1.17 40c9c468DCpMe542varOolW1Xc68ew tools/python/xen/xend/server/SrvBase.py 1.18 40c9c468IxQabrKJSWs0aEjl-27mRQ tools/python/xen/xend/server/SrvConsole.py 1.19 40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/python/xen/xend/server/SrvConsoleDir.py 1.20 @@ -257,7 +260,6 @@ 40c9c4692hckPol_EK0EGB16ZyDsyQ tools/pyt 1.21 40c9c469N2-b3GqpLHHHPZykJPLVvA tools/python/xen/xend/server/channel.py 1.22 40c9c469hJ_IlatRne-9QEa0-wlquw tools/python/xen/xend/server/console.py 1.23 40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/python/xen/xend/server/controller.py 1.24 -40c9c469vHh-qLiiubdbKEQbJf18Zw tools/python/xen/xend/server/cstruct.py 1.25 40d83983OXjt-y3HjSCcuoPp9rzvmw tools/python/xen/xend/server/domain.py 1.26 40c9c469yrm31i60pGKslTi2Zgpotg tools/python/xen/xend/server/messages.py 1.27 40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/python/xen/xend/server/netif.py 1.28 @@ -265,6 +267,7 @@ 40c9c469ZqILEQ8x6yWy0_51jopiCg tools/pyt 1.29 40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/python/xen/xend/sxp.py 1.30 40d05079aFRp6NQdo5wIh5Ly31c0cg tools/python/xen/xm/__init__.py 1.31 40cf2937gKQcATgXKGtNeWb1PDH5nA tools/python/xen/xm/create.py 1.32 +40e41cd2w0I4En6qrJn4em8HkK_oxQ tools/python/xen/xm/help.py 1.33 40cf2937isyS250zyd0Q2GuEDoNXfQ tools/python/xen/xm/main.py 1.34 40cf2937PSslwBliN1g7ofDy2H_RhA tools/python/xen/xm/opts.py 1.35 40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/python/xen/xm/shutdown.py 1.36 @@ -274,6 +277,32 @@ 4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xen 1.37 403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c 1.38 403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format 1.39 4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1 1.40 +40e9808eHO3QprCFKg9l2JJzgt2voA tools/xfrd/Make.xfrd 1.41 +40e9808epTR4zWrYjGUnaaynK20Q5A tools/xfrd/Makefile 1.42 +40e9808eysqT4VNDlJFqsZB2rdg4Qw tools/xfrd/connection.c 1.43 +40e9808eyXfJUi4E0C3WSgrEXqQ1sQ tools/xfrd/connection.h 1.44 +40e9808eULGwffNOE4kBrAfZ9YAVMA tools/xfrd/debug.h 1.45 +40e9808eyjiahG5uF6AMelNVujBzCg tools/xfrd/enum.c 1.46 +40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/xfrd/enum.h 1.47 +40e9808easXCzzAZQodEfKAhgUXSPA tools/xfrd/hash_table.c 1.48 +40e9808e94BNXIVVKBFHC3rnkvwtJg tools/xfrd/hash_table.h 1.49 +40e9808epW9iHcLXuO3QfUfLzB7onw tools/xfrd/lexis.c 1.50 +40e9808egccMhCizayQRGtpBA3L5MQ tools/xfrd/lexis.h 1.51 +40e9808ePADCSKL1YgGCt2TbYPnYkw tools/xfrd/lzi_stream.c 1.52 +40e9808eDNAdpF71o5teYb9DTT-PRw tools/xfrd/lzi_stream.h 1.53 +40e9808eQxi0EzTcPJtosrzxEIjA-Q tools/xfrd/marshal.c 1.54 +40e9808etg13xfRm0Lqd8vY-jHOoTg tools/xfrd/marshal.h 1.55 +40e9808eCsmywryb036TdtRMJHDMmQ tools/xfrd/select.c 1.56 +40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h 1.57 +40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c 1.58 +40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h 1.59 +40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c 1.60 +40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h 1.61 +40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c 1.62 +40e9808eHviFFIwdUKOA234uIeifjA tools/xfrd/xen_domain.h 1.63 +40e9808eIFeV-MDCNyVTNt5NfMPKeQ tools/xfrd/xfrd.c 1.64 +40e9808eGIbOoSNJRiwWK2C3mjGWaA tools/xfrd/xfrd.h 1.65 +40e9808eHXvs_5eggj9McD_J90mhNw tools/xfrd/xfrdClient.py 1.66 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING 1.67 3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile 1.68 3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk 1.69 @@ -285,8 +314,7 @@ 3ddb79bcSC_LvnmFlX-T5iTgaR0SKg xen/arch/ 1.70 40e42bdbNu4MjI750THP_8J1S-Sa0g xen/arch/x86/boot/x86_64.S 1.71 3ddb79bcUrk2EIaM5VsT6wUudH1kkg xen/arch/x86/delay.c 1.72 40e34414WiQO4h2m3tcpaCPn7SyYyg xen/arch/x86/dom0_ops.c 1.73 -3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/arch/x86/domain_page.c 1.74 -3ddb79bcecupHj56ZbTa3B0FxDowMg xen/arch/x86/entry.S 1.75 +3ddb79bc1_2bAt67x9MFCP4AZrQnvQ xen/arch/x86/domain.c 1.76 3ddb79bcY5zW7KhvI9gvfuPi3ZumEg xen/arch/x86/extable.c 1.77 3fe443fdDDb0Sw6NQBCk4GQapayfTA xen/arch/x86/flushtlb.c 1.78 3ddb79bcesE5E-lS4QhRhlqXxqj9cA xen/arch/x86/i387.c 1.79 @@ -294,7 +322,6 @@ 3ddb79bcCAq6IpdkHueChoVTfXqEQQ xen/arch/ 1.80 3ddb79bcBit4xJXbwtX0kb1hh2uO1Q xen/arch/x86/idle0_task.c 1.81 3ddb79bcKIkRR0kqWaJhe5VUDkMdxg xen/arch/x86/io_apic.c 1.82 3ddb79bdqfIcjkz_h9Hvtp8Tk_19Zw xen/arch/x86/irq.c 1.83 -3ddb79bcHwuCQDjBICDTSis52hWguw xen/arch/x86/mm.c 1.84 3ddb79bdS4UeWWXDH-FaBKqcpMFcnw xen/arch/x86/mpparse.c 1.85 3f12cff65EV3qOG2j37Qm0ShgvXGRw xen/arch/x86/nmi.c 1.86 3ddb79bdHe6_Uij4-glW91vInNtBYQ xen/arch/x86/pci-irq.c 1.87 @@ -303,7 +330,6 @@ 3ddb79bdeJ7_86z03yTAPIeeywOg3Q xen/arch/ 1.88 3ddb79bdIKgipvGoqExEQ7jawfVowA xen/arch/x86/pci-x86.h 1.89 40a4dfced2dnSzbKgJFlD3chKHexjQ xen/arch/x86/pdb-linux.c 1.90 4022a73czgX7d-2zfF_cb33oVemApQ xen/arch/x86/pdb-stub.c 1.91 -3ddb79bc1_2bAt67x9MFCP4AZrQnvQ xen/arch/x86/process.c 1.92 3ddb79bc7KxGCEJsgBnkDX7XjD_ZEQ xen/arch/x86/rwlock.c 1.93 3ddb79bcrD6Z_rUvSDgrvjyb4846Eg xen/arch/x86/setup.c 1.94 405b8599xI_PoEr3zZoJ2on-jdn7iw xen/arch/x86/shadow.c 1.95 @@ -312,8 +338,14 @@ 3ddb79bcfUN3-UBCPzX26IU8bq-3aw xen/arch/ 1.96 3ddb79bc-Udq7ol-NX4q9XsYnN7A2Q xen/arch/x86/time.c 1.97 3ddb79bccYVzXZJyVaxuv5T42Z1Fsw xen/arch/x86/trampoline.S 1.98 3ddb79bcOftONV9h4QCxXOfiT0h91w xen/arch/x86/traps.c 1.99 -3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/usercopy.c 1.100 -3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/xen.lds 1.101 +3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/arch/x86/x86_32/domain_page.c 1.102 +3ddb79bcecupHj56ZbTa3B0FxDowMg xen/arch/x86/x86_32/entry.S 1.103 +3ddb79bcHwuCQDjBICDTSis52hWguw xen/arch/x86/x86_32/mm.c 1.104 +3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/x86_32/usercopy.c 1.105 +3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/x86_32/xen.lds 1.106 +40e96d3aLDI-nViMuYneD7VKYlZrVg xen/arch/x86/x86_64/entry.S 1.107 +40e96d3ahBTZqbTViInnq0lM03vs7A xen/arch/x86/x86_64/usercopy.c 1.108 +40e96d3akN3Hu_J5Bk-WXD8OGscrYQ xen/arch/x86/x86_64/xen.lds 1.109 3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile 1.110 3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c 1.111 4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c
2.1 --- a/docs/HOWTOs/XenDebugger-HOWTO Tue Jul 06 17:25:40 2004 +0000 2.2 +++ b/docs/HOWTOs/XenDebugger-HOWTO Tue Jul 06 17:27:27 2004 +0000 2.3 @@ -77,7 +77,7 @@ Serial Port Configuration 2.4 one stream (without the high bit) is the console and 2.5 one stream (with the high bit stripped) is the pdb communication. 2.6 2.7 - See: xeno.bk/tools/nsplitd 2.8 + See: xeno.bk/tools/misc/nsplitd 2.9 2.10 nsplitd configuration 2.11 --------------------- 2.12 @@ -107,7 +107,7 @@ Serial Port Configuration 2.13 characters received. 2.14 2.15 You can connect to the nsplitd using 2.16 - 'tools/xenctl/lib/console_client.py <host> <port>' 2.17 + 'tools/misc/xencons <host> <port>' 2.18 2.19 GDB 6.0 2.20 pdb has been tested with gdb 6.0. It should also work with
3.1 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/common.h Tue Jul 06 17:25:40 2004 +0000 3.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/common.h Tue Jul 06 17:27:27 2004 +0000 3.3 @@ -19,7 +19,7 @@ 3.4 #define ASSERT(_p) \ 3.5 if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \ 3.6 __LINE__, __FILE__); *(int*)0=0; } 3.7 -#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ 3.8 +#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ 3.9 __FILE__ , __LINE__ , ## _a ) 3.10 #else 3.11 #define ASSERT(_p) ((void)0)
4.1 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/interface.c Tue Jul 06 17:25:40 2004 +0000 4.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/backend/interface.c Tue Jul 06 17:27:27 2004 +0000 4.3 @@ -217,7 +217,7 @@ int blkif_disconnect(blkif_be_disconnect 4.4 blkif->status = DISCONNECTING; 4.5 blkif->disconnect_rspid = rsp_id; 4.6 wmb(); /* Let other CPUs see the status change. */ 4.7 - free_irq(blkif->irq, NULL); 4.8 + free_irq(blkif->irq, blkif); 4.9 blkif_deschedule(blkif); 4.10 blkif_put(blkif); 4.11 }
5.1 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c Tue Jul 06 17:25:40 2004 +0000 5.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/blkif/frontend/main.c Tue Jul 06 17:27:27 2004 +0000 5.3 @@ -616,7 +616,7 @@ static void blkif_status_change(blkif_fe 5.4 5.5 printk(KERN_INFO "VBD driver recovery in progress\n"); 5.6 5.7 - /* Prevent new requests being issued until we've fixed things up. */ 5.8 + /* Prevent new requests being issued until we fix things up. */ 5.9 spin_lock_irq(&io_request_lock); 5.10 recovery = 1; 5.11 blkif_state = BLKIF_STATE_DISCONNECTED;
6.1 --- a/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c Tue Jul 06 17:25:40 2004 +0000 6.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/drivers/netif/backend/interface.c Tue Jul 06 17:27:27 2004 +0000 6.3 @@ -266,7 +266,7 @@ int netif_disconnect(netif_be_disconnect 6.4 netif->disconnect_rspid = rsp_id; 6.5 wmb(); /* Let other CPUs see the status change. */ 6.6 netif_stop_queue(netif->dev); 6.7 - free_irq(netif->irq, NULL); 6.8 + free_irq(netif->irq, netif); 6.9 netif_deschedule(netif); 6.10 netif_put(netif); 6.11 }
7.1 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/process.c Tue Jul 06 17:25:40 2004 +0000 7.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/process.c Tue Jul 06 17:27:27 2004 +0000 7.3 @@ -115,7 +115,7 @@ void cpu_idle (void) 7.4 } 7.5 } 7.6 7.7 -void machine_restart(char * __unused) 7.8 +void machine_restart(char *__unused) 7.9 { 7.10 /* We really want to get pending console data out before we die. */ 7.11 extern void xencons_force_flush(void); 7.12 @@ -128,7 +128,11 @@ void machine_halt(void) 7.13 /* We really want to get pending console data out before we die. */ 7.14 extern void xencons_force_flush(void); 7.15 xencons_force_flush(); 7.16 - HYPERVISOR_shutdown(); 7.17 + for ( ; ; ) /* loop without wasting cpu cycles */ 7.18 + { 7.19 + HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_pending = 0; 7.20 + HYPERVISOR_block(); 7.21 + } 7.22 } 7.23 7.24 void machine_power_off(void)
8.1 --- a/tools/examples/xmdefaults Tue Jul 06 17:25:40 2004 +0000 8.2 +++ b/tools/examples/xmdefaults Tue Jul 06 17:27:27 2004 +0000 8.3 @@ -2,17 +2,23 @@ 8.4 #============================================================================ 8.5 # Python defaults setup for 'xm create'. 8.6 # Edit this file to reflect the configuration of your system. 8.7 -# This file expects the variable 'vmid' to be set. 8.8 #============================================================================ 8.9 8.10 -try: 8.11 - vmid = int(vmid) # convert to integer 8.12 -except: 8.13 - raise ValueError, "Variable 'vmid' must be an integer" 8.14 +# Define script variables here. 8.15 +# xm_vars is defined automatically, use xm_vars.var() to define a variable. 8.16 8.17 -if vmid <= 0: 8.18 - raise ValueError, "Variable 'vmid' must be greater than 0" 8.19 +def vmid_check(var, val): 8.20 + val = int(val) 8.21 + if val <= 0: 8.22 + raise ValueError 8.23 + return val 8.24 + 8.25 +xm_vars.var('vmid', 8.26 + use="Virtual machine id. Integer greater than 0.", 8.27 + check=vmid_check) 8.28 8.29 +# This checks the script variables. 8.30 +xm_vars.check() 8.31 8.32 #---------------------------------------------------------------------------- 8.33 # Kernel image file. 8.34 @@ -87,6 +93,6 @@ extra = "4 VMID=%d usr=/dev/sda6" % vmid 8.35 #---------------------------------------------------------------------------- 8.36 # Set according to whether you want the domain restarted when it exits. 8.37 # The default is False. 8.38 -#restart = True 8.39 +#autorestart = True 8.40 8.41 #============================================================================
9.1 --- a/tools/examples/xmnetbsd Tue Jul 06 17:25:40 2004 +0000 9.2 +++ b/tools/examples/xmnetbsd Tue Jul 06 17:27:27 2004 +0000 9.3 @@ -2,24 +2,23 @@ 9.4 #============================================================================ 9.5 # Python defaults setup for 'xm create'. 9.6 # Edit this file to reflect the configuration of your system. 9.7 -# This file expects the variable 'vmid' to be set. 9.8 #============================================================================ 9.9 9.10 -def config_usage (): 9.11 - print >>sys.stderr,""" 9.12 -The config file '%s' requires the following variable to be defined: 9.13 - vmid -- Numeric identifier for the new domain, used to calculate 9.14 - the VM's IP address and root partition. E.g. -Dvmid=1 9.15 -""" % config_file 9.16 - 9.17 +# Define script variables here. 9.18 +# xm_vars is defined automatically, use xm_vars.var() to define a variable. 9.19 9.20 -try: 9.21 - vmid = int(vmid) # convert to integer 9.22 -except: 9.23 - raise ValueError, "Variable 'vmid' must be an integer" 9.24 +def vmid_check(var, val): 9.25 + val = int(val) 9.26 + if val <= 0: 9.27 + raise ValueError 9.28 + return val 9.29 + 9.30 +xm_vars.var('vmid', 9.31 + use="Virtual machine id. Integer greater than 0.", 9.32 + check=vmid_check) 9.33 9.34 -if vmid <= 0: 9.35 - raise ValueError, "Variable 'vmid' must be greater than 0" 9.36 +# This checks the script variables. 9.37 +xm_vars.check() 9.38 9.39 #---------------------------------------------------------------------------- 9.40 # Kernel image file. 9.41 @@ -97,6 +96,6 @@ extra = "4 VMID=%d bootdev=xennet0" % vm 9.42 #---------------------------------------------------------------------------- 9.43 # Set according to whether you want the domain restarted when it exits. 9.44 # The default is False. 9.45 -#restart = True 9.46 +#autorestart = True 9.47 9.48 #============================================================================
10.1 --- a/tools/libxutil/Makefile Tue Jul 06 17:25:40 2004 +0000 10.2 +++ b/tools/libxutil/Makefile Tue Jul 06 17:27:27 2004 +0000 10.3 @@ -8,7 +8,7 @@ LIB_SRCS += allocate.c 10.4 LIB_SRCS += file_stream.c 10.5 LIB_SRCS += gzip_stream.c 10.6 LIB_SRCS += iostream.c 10.7 -LIB_SRCS += sys_net.c 10.8 +#LIB_SRCS += sys_net.c 10.9 LIB_SRCS += sys_string.c 10.10 10.11 LIB_OBJS := $(LIB_SRCS:.c=.o)
11.1 --- a/tools/libxutil/allocate.h Tue Jul 06 17:25:40 2004 +0000 11.2 +++ b/tools/libxutil/allocate.h Tue Jul 06 17:27:27 2004 +0000 11.3 @@ -16,8 +16,8 @@ 11.4 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 11.5 */ 11.6 11.7 -#ifndef _XEN_LIB_ALLOCATE_H_ 11.8 -#define _XEN_LIB_ALLOCATE_H_ 11.9 +#ifndef _XUTIL_ALLOCATE_H_ 11.10 +#define _XUTIL_ALLOCATE_H_ 11.11 11.12 /** Allocate memory for a given type, and cast. */ 11.13 #define ALLOCATE(ctype) (ctype *)allocate(sizeof(ctype)) 11.14 @@ -33,7 +33,7 @@ extern void memzero(void *p, int size); 11.15 typedef void AllocateFailedFn(int size, int type); 11.16 extern AllocateFailedFn *allocate_failed_fn; 11.17 11.18 -#endif /* _XEN_LIB_ALLOCATE_H_ */ 11.19 +#endif /* _XUTIL_ALLOCATE_H_ */ 11.20 11.21 11.22
12.1 --- a/tools/libxutil/file_stream.h Tue Jul 06 17:25:40 2004 +0000 12.2 +++ b/tools/libxutil/file_stream.h Tue Jul 06 17:27:27 2004 +0000 12.3 @@ -16,8 +16,8 @@ 12.4 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 12.5 */ 12.6 12.7 -#ifndef _XEN_LIB_FILE_STREAM_H_ 12.8 -#define _XEN_LIB_FILE_STREAM_H_ 12.9 +#ifndef _XUTIL_FILE_STREAM_H_ 12.10 +#define _XUTIL_FILE_STREAM_H_ 12.11 12.12 #ifndef __KERNEL__ 12.13 #include "iostream.h" 12.14 @@ -32,4 +32,4 @@ extern IOStream get_stream_stdin(void); 12.15 12.16 extern int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size); 12.17 #endif 12.18 -#endif /* !_XEN_LIB_FILE_STREAM_H_ */ 12.19 +#endif /* !_XUTIL_FILE_STREAM_H_ */
13.1 --- a/tools/libxutil/gzip_stream.c Tue Jul 06 17:25:40 2004 +0000 13.2 +++ b/tools/libxutil/gzip_stream.c Tue Jul 06 17:27:27 2004 +0000 13.3 @@ -1,4 +1,3 @@ 13.4 -/* $Id: gzip_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */ 13.5 /* 13.6 * Copyright (C) 2003 Hewlett-Packard Company. 13.7 *
14.1 --- a/tools/libxutil/gzip_stream.h Tue Jul 06 17:25:40 2004 +0000 14.2 +++ b/tools/libxutil/gzip_stream.h Tue Jul 06 17:27:27 2004 +0000 14.3 @@ -1,4 +1,3 @@ 14.4 -#/* $Id: gzip_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */ 14.5 /* 14.6 * Copyright (C) 2003 Hewlett-Packard Company. 14.7 * 14.8 @@ -17,8 +16,8 @@ 14.9 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14.10 */ 14.11 14.12 -#ifndef _SP_GZIP_STREAM_H_ 14.13 -#define _SP_GZIP_STREAM_H_ 14.14 +#ifndef _XUTIL_GZIP_STREAM_H_ 14.15 +#define _XUTIL_GZIP_STREAM_H_ 14.16 14.17 #ifndef __KERNEL__ 14.18 #include "iostream.h" 14.19 @@ -28,4 +27,4 @@ extern IOStream *gzip_stream_new(gzFile 14.20 extern IOStream *gzip_stream_fopen(const char *file, const char *flags); 14.21 extern IOStream *gzip_stream_fdopen(int fd, const char *flags); 14.22 #endif 14.23 -#endif /* !_SP_FILE_STREAM_H_ */ 14.24 +#endif /* !_XUTIL_GZIP_STREAM_H_ */
15.1 --- a/tools/libxutil/kernel_stream.h Tue Jul 06 17:25:40 2004 +0000 15.2 +++ b/tools/libxutil/kernel_stream.h Tue Jul 06 17:27:27 2004 +0000 15.3 @@ -16,8 +16,8 @@ 15.4 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15.5 */ 15.6 15.7 -#ifndef _XEN_LIB_KERNEL_STREAM_H_ 15.8 -#define _XEN_LIB_KERNEL_STREAM_H_ 15.9 +#ifndef _XUTIL_KERNEL_STREAM_H_ 15.10 +#define _XUTIL_KERNEL_STREAM_H_ 15.11 15.12 #ifdef __KERNEL__ 15.13 #include "iostream.h" 15.14 @@ -26,4 +26,4 @@ extern IOStream get_stream_kernel(void); 15.15 #define get_stream_stdout get_stream_kernel 15.16 15.17 #endif /* __KERNEL__ */ 15.18 -#endif /* !_XEN_LIB_KERNEL_STREAM_H_ */ 15.19 +#endif /* !_XUTIL_KERNEL_STREAM_H_ */
16.1 --- a/tools/libxutil/string_stream.c Tue Jul 06 17:25:40 2004 +0000 16.2 +++ b/tools/libxutil/string_stream.c Tue Jul 06 17:27:27 2004 +0000 16.3 @@ -25,8 +25,6 @@ 16.4 #include "string_stream.h" 16.5 #include "allocate.h" 16.6 16.7 -static int string_print(IOStream *io, const char *msg, va_list args); 16.8 -static int string_getc(IOStream *io); 16.9 static int string_error(IOStream *io); 16.10 static int string_close(IOStream *io); 16.11 static void string_free(IOStream *io); 16.12 @@ -49,45 +47,6 @@ static inline StringData *get_string_dat 16.13 return (StringData*)io->data; 16.14 } 16.15 16.16 -/** Read a character from a string stream. 16.17 - * 16.18 - * @param io string stream 16.19 - * @return character read, IOSTREAM_EOF if no more input 16.20 - */ 16.21 -static int string_getc(IOStream *io){ 16.22 - StringData *data = get_string_data(io); 16.23 - int c = IOSTREAM_EOF; 16.24 - char *s = data->in; 16.25 - 16.26 - if(s && s < data->end){ 16.27 - c = (unsigned)*s; 16.28 - data->in = s+1; 16.29 - } 16.30 - return c; 16.31 -} 16.32 - 16.33 -/** Print to a string stream. 16.34 - * Formats the data to an internal buffer and prints it. 16.35 - * The formatted data must fit into the internal buffer. 16.36 - * 16.37 - * @param io string stream 16.38 - * @param format print format 16.39 - * @param args print arguments 16.40 - * @return result of the print 16.41 - */ 16.42 -static int string_print(IOStream *io, const char *msg, va_list args){ 16.43 - StringData *data = get_string_data(io); 16.44 - int k = data->end - data->out; 16.45 - int n = vsnprintf(data->out, k, (char*)msg, args); 16.46 - if(n < 0 || n > k ){ 16.47 - n = k; 16.48 - IOStream_close(io); 16.49 - } else { 16.50 - data->out += n; 16.51 - } 16.52 - return n; 16.53 -} 16.54 - 16.55 /** Test if a string stream has an error. 16.56 * 16.57 * @param io string stream 16.58 @@ -118,7 +77,7 @@ static int string_close(IOStream *io){ 16.59 */ 16.60 static void string_free(IOStream *io){ 16.61 StringData *data = get_string_data(io); 16.62 - zero(data, sizeof(*data)); 16.63 + memzero(data, sizeof(*data)); 16.64 deallocate(data); 16.65 } 16.66 16.67 @@ -139,13 +98,13 @@ IOMethods *string_stream_get_methods(voi 16.68 */ 16.69 void string_stream_init(IOStream *io, StringData *data, char *s, int n){ 16.70 if(data && io){ 16.71 - zero(data, sizeof(*data)); 16.72 + memzero(data, sizeof(*data)); 16.73 data->string = (char*)s; 16.74 data->in = data->string; 16.75 data->out = data->string; 16.76 data->size = n; 16.77 data->end = data->string + n; 16.78 - zero(io, sizeof(*io)); 16.79 + memzero(io, sizeof(*io)); 16.80 io->methods = &string_methods; 16.81 io->data = data; 16.82 }
17.1 --- a/tools/libxutil/string_stream.h Tue Jul 06 17:25:40 2004 +0000 17.2 +++ b/tools/libxutil/string_stream.h Tue Jul 06 17:27:27 2004 +0000 17.3 @@ -1,4 +1,3 @@ 17.4 -/* $Id: string_stream.h,v 1.1 2003/08/22 14:25:48 mjw Exp $ */ 17.5 /* 17.6 * Copyright (C) 2001, 2002 Hewlett-Packard Company. 17.7 * 17.8 @@ -17,8 +16,8 @@ 17.9 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17.10 */ 17.11 17.12 -#ifndef _SP_STRING_STREAM_H_ 17.13 -#define _SP_STRING_STREAM_H_ 17.14 +#ifndef _XUTIL_STRING_STREAM_H_ 17.15 +#define _XUTIL_STRING_STREAM_H_ 17.16 17.17 #include "iostream.h" 17.18 17.19 @@ -43,4 +42,4 @@ extern IOMethods *string_stream_get_meth 17.20 extern IOStream *string_stream_new(char *s, int n); 17.21 extern void string_stream_init(IOStream *stream, StringData *data, char *s, int n); 17.22 17.23 -#endif /* !_SP_STRING_STREAM_H_ */ 17.24 +#endif /* !_XUTIL_STRING_STREAM_H_ */
18.1 --- a/tools/libxutil/sys_net.h Tue Jul 06 17:25:40 2004 +0000 18.2 +++ b/tools/libxutil/sys_net.h Tue Jul 06 17:27:27 2004 +0000 18.3 @@ -16,8 +16,8 @@ 18.4 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18.5 */ 18.6 18.7 -#ifndef _XEN_LIB_SYS_NET_H_ 18.8 -#define _XEN_LIB_SYS_NET_H_ 18.9 +#ifndef _XUTIL_SYS_NET_H_ 18.10 +#define _XUTIL_SYS_NET_H_ 18.11 /** @file 18.12 * 18.13 * Replacement for standard network includes. 18.14 @@ -72,7 +72,7 @@ extern int inet_aton(const char *address 18.15 extern char *mac_ntoa(const unsigned char *macaddr); 18.16 extern int mac_aton(const char *addr, unsigned char *macaddr); 18.17 18.18 -#endif /* !_SP_SYS_NET_H_ */ 18.19 +#endif /* !_XUTIL_SYS_NET_H_ */ 18.20 18.21 18.22
19.1 --- a/tools/libxutil/sys_string.h Tue Jul 06 17:25:40 2004 +0000 19.2 +++ b/tools/libxutil/sys_string.h Tue Jul 06 17:27:27 2004 +0000 19.3 @@ -16,8 +16,8 @@ 19.4 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19.5 */ 19.6 19.7 -#ifndef _XEN_LIB_SYS_STRING_H_ 19.8 -#define _XEN_LIB_SYS_STRING_H_ 19.9 +#ifndef _XUTIL_SYS_STRING_H_ 19.10 +#define _XUTIL_SYS_STRING_H_ 19.11 /** @file 19.12 * Replacement for standard string includes. 19.13 * Works in user or kernel code. 19.14 @@ -88,4 +88,4 @@ static inline size_t strnlen(const char 19.15 extern int convert_atoul(const char *s, unsigned long *v); 19.16 extern int path_concat(char *s, char *t, char **val); 19.17 19.18 -#endif /* !_XEN_LIB_SYS_STRING_H_ */ 19.19 +#endif /* !_XUTIL_SYS_STRING_H_ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/tools/misc/nsplitd/Makefile Tue Jul 06 17:27:27 2004 +0000 20.3 @@ -0,0 +1,22 @@ 20.4 + 20.5 +CC = gcc 20.6 +CFLAGS = -Wall -O3 20.7 +CFILES = $(wildcard *.c) 20.8 + 20.9 +HDRS = $(wildcard *.h) 20.10 +OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) 20.11 + 20.12 +TARGET = nsplitd 20.13 + 20.14 +all: $(TARGET) 20.15 + 20.16 +install: all 20.17 + 20.18 +clean: 20.19 + $(RM) *.o $(TARGET) *~ 20.20 + 20.21 +$(TARGET): $(OBJS) 20.22 + $(CC) $(CFLAGS) -o $@ $^ 20.23 + 20.24 +%.o: %.c $(HDRS) Makefile 20.25 + $(CC) $(CFLAGS) -c -o $@ $<
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/tools/misc/nsplitd/nsplitd.c Tue Jul 06 17:27:27 2004 +0000 21.3 @@ -0,0 +1,686 @@ 21.4 +/* 21.5 + * nsplitd.c 21.6 + * --------- 21.7 + * 21.8 + * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ 21.9 + * 21.10 + * Copyright (c) 1995, University of Cambridge Computer Laboratory, 21.11 + * Copyright (c) 1995, Richard Black, All Rights Reserved. 21.12 + * 21.13 + * 21.14 + * A complete re-implementation of DME's nsplitd for use from inetd 21.15 + * 21.16 + */ 21.17 + 21.18 +/* The basic stream comes in (via inetd) and we then conenct to 21.19 + * somewhere else providing a loop-through service, except we offer 21.20 + * two other ports for connection - one of which gets a second channel 21.21 + * using the top bit to distinguish, and the other is a master control 21.22 + * port (normally used for gdb) which gets complete exclusive access 21.23 + * for its duration. 21.24 + * 21.25 + * Originally designed for multiplexing a xwcons/telnet with a gdb 21.26 + * post-mortem debugging session. 21.27 + * 21.28 + * Here is a picture: 21.29 + * 21.30 + * port0 (from inetd) 21.31 + * 8-bit connection / 21.32 + * made by us <----> nsplitd <-----gdbport (default port0+2) 21.33 + * to host:port/tcp |\ 21.34 + * | port1 (default port0+1) 21.35 + * \ 21.36 + * control (default port0+3) 21.37 + * 21.38 + * If port1 is explicitly disabled (through a command-line option) then 21.39 + * port0 becomes 8-bit clean. 21.40 + */ 21.41 + 21.42 +/* 21.43 + * N.B.: We do NOT support 8 bit stdin/stdout usage on a 21.44 + * /dev/... because to do that right involves much messing with ioctl 21.45 + * and TIOC... etc. If you want to do that sort of thing then the 21.46 + * right way to do it is to chain this onto wconsd (which does know 21.47 + * about and understand all the ioctl and TIOC grief). 21.48 + */ 21.49 + 21.50 +#include <sys/types.h> 21.51 +#include <stdarg.h> 21.52 +#include <stdio.h> 21.53 +#include <stdlib.h> 21.54 +#include <assert.h> 21.55 +#include <errno.h> 21.56 +#include <unistd.h> 21.57 +#include <ctype.h> 21.58 +#include <netdb.h> 21.59 +#include <string.h> 21.60 + 21.61 +#include <sys/time.h> 21.62 +#include <sys/signal.h> 21.63 +#include <sys/socket.h> 21.64 +#include <netinet/in.h> 21.65 +#include <netinet/tcp.h> 21.66 +#include <arpa/inet.h> 21.67 +#include <sys/ioctl.h> 21.68 +#include <syslog.h> 21.69 + 21.70 +#ifndef FALSE 21.71 +#define FALSE 0 21.72 +#endif 21.73 +#ifndef TRUE 21.74 +#define TRUE 1 21.75 +#endif 21.76 + 21.77 +#ifndef LOG_DAEMON 21.78 +#define LOG_DAEMON 0 21.79 +#endif 21.80 + 21.81 +#define DB(x) /* ((x), fflush(stderr)) */ 21.82 + 21.83 +extern char *optarg; 21.84 + 21.85 +extern int optind, opterr, optopt; 21.86 + 21.87 +static char *prog_name; 21.88 + 21.89 +static void usage(void) 21.90 +{ 21.91 + fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n", 21.92 + prog_name); 21.93 + fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]" 21.94 + "[-c<ctlport>][-8] host:service\n", 21.95 + prog_name); 21.96 + exit(1); 21.97 +} 21.98 + 21.99 +static void fault(char *format, ...) 21.100 +{ 21.101 + va_list ap; 21.102 + char logbuf[1024]; 21.103 + 21.104 + va_start(ap, format); 21.105 + fprintf(stderr, "%s: ", prog_name); 21.106 + vfprintf(stderr, format, ap); 21.107 + fflush(stderr); 21.108 + va_end(ap); 21.109 + 21.110 + /* XXX This is a bit dubious, but there is no vsyslog */ 21.111 + va_start(ap, format); 21.112 + vsprintf(logbuf, format, ap); 21.113 + syslog(LOG_ERR, logbuf); 21.114 + va_end(ap); 21.115 + exit(1); 21.116 +} 21.117 + 21.118 +static int getservice(char *name, unsigned short *port) 21.119 +{ 21.120 + struct servent *se; 21.121 + 21.122 + if (!name) return -1; 21.123 + 21.124 + if (isdigit(name[0])) 21.125 + *port = atoi(name); 21.126 + else 21.127 + { 21.128 + if (!(se = getservbyname(name, "tcp"))) 21.129 + return -1; 21.130 + *port = ntohs(se->s_port); 21.131 + } 21.132 + return 0; 21.133 +} 21.134 + 21.135 +/* 21.136 + * connect_host: connect to ("name", "port") 21.137 + */ 21.138 +static int connect_host (char *name, unsigned int port) 21.139 +{ 21.140 + int fd; 21.141 + struct hostent *hostent; 21.142 + struct sockaddr_in sin; 21.143 + int on; 21.144 + 21.145 + if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) 21.146 + fault("socket"); 21.147 + 21.148 + if (!(hostent = gethostbyname(name))) 21.149 + fault("gethostbyname: %s: %s\n", name, strerror(errno)); 21.150 + 21.151 + memset(&sin, 0, sizeof(sin)); 21.152 + sin.sin_family = AF_INET; 21.153 + sin.sin_port = htons (port); 21.154 + memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr)); 21.155 + 21.156 + if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) 21.157 + fault("connect: %s:%u: %s\n", name, port, strerror(errno)); 21.158 + 21.159 + on = 1; 21.160 + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0) 21.161 + syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 21.162 + 21.163 + on = 1; 21.164 + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 21.165 + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 21.166 + 21.167 + return fd; 21.168 +} 21.169 + 21.170 +/* 21.171 + * open a tcp socket and start listening for connections on it 21.172 + */ 21.173 +static int startlistening(unsigned short port) 21.174 +{ 21.175 + int fd, on; 21.176 + struct sockaddr_in sin; 21.177 + 21.178 + if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) 21.179 + fault("socket"); 21.180 + 21.181 + on = 1; 21.182 + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) 21.183 + syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m"); 21.184 + 21.185 + memset(&sin, 0, sizeof(sin)); 21.186 + sin.sin_family = AF_INET; 21.187 + sin.sin_port = htons (port); 21.188 + sin.sin_addr.s_addr = INADDR_ANY; 21.189 + if (bind(fd, &sin, sizeof(sin)) < 0) 21.190 + fault("bind: %u: %s\n", port, strerror(errno)); 21.191 + 21.192 + if (listen(fd, 1) < 0) 21.193 + fault("listen: %s\n", strerror(errno)); 21.194 + 21.195 + return fd; 21.196 +} 21.197 + 21.198 +static void noblock(int fd) 21.199 +{ 21.200 + int on=1; 21.201 + 21.202 + if (ioctl(fd, FIONBIO, &on) < 0) 21.203 + fault("ioctl: FIONBIO: %s\n", strerror(errno)); 21.204 +} 21.205 + 21.206 + 21.207 +/* You might not believe this, but fd_sets don't have to be a 32-bit 21.208 + * integer. In particular, in glibc2 it is an array of unsigned 21.209 + * longs. Hence, this hacked up FD_SET_rjb() that works out if it 21.210 + * would have been a nop. */ 21.211 +#define FD_SET_rjb(fd, setp) \ 21.212 +do { \ 21.213 + if ((fd) != 32) \ 21.214 + FD_SET((fd), (setp)); \ 21.215 +} while(0) 21.216 + 21.217 +#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0) 21.218 + 21.219 +#define MAXSIZE 256 21.220 + 21.221 +/* ----------------------------------------------------------------- 21.222 + * The main bit of the algorithm. Note we use 32 to mean not connected 21.223 + * because this gives us 1<<32 == 0. We could have done this one 21.224 + * character at a time, but that would have been very inefficient and 21.225 + * not the unix way. */ 21.226 +static int debug; 21.227 + 21.228 +static void doit(int actl, int acto, int lish, int lisg, int lisc) 21.229 +{ 21.230 + int acth, actg, actc; 21.231 + int gdbmode = FALSE; 21.232 + char gibuf[MAXSIZE], oibuf[MAXSIZE]; 21.233 + char libuf[MAXSIZE], lobuf[MAXSIZE]; 21.234 + char hibuf[MAXSIZE], hobuf[MAXSIZE]; 21.235 + char ctlbuf[MAXSIZE]; 21.236 + fd_set rdfs, wrfs, exfs; 21.237 + int gicc, oicc, licc, locc, hicc, hocc, ctlcc; 21.238 + char *giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr; 21.239 + int rc, fromlen; 21.240 + struct sockaddr_in from; 21.241 + 21.242 + gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0; 21.243 + acth = actg = actc = 32; /* XXX yummy */ 21.244 + 21.245 + noblock(actl); 21.246 + noblock(acto); 21.247 + 21.248 + for(;;) 21.249 + { 21.250 + FD_ZERO(&rdfs); 21.251 + FD_ZERO(&wrfs); 21.252 + FD_ZERO(&exfs); 21.253 + 21.254 + /* always take input from the control port (if it's connected) */ 21.255 + FD_SET_rjb(actc, &rdfs); 21.256 + 21.257 + if (gdbmode) 21.258 + { 21.259 + if (oicc) 21.260 + FD_SET_rjb(actg, &wrfs); 21.261 + else 21.262 + FD_SET_rjb(acto, &rdfs); 21.263 + 21.264 + if (gicc) 21.265 + FD_SET_rjb(acto, &wrfs); 21.266 + else 21.267 + FD_SET_rjb(actg, &rdfs); 21.268 + } 21.269 + else 21.270 + { 21.271 + /* There is no such thing as oibuf because its been split into 21.272 + * lobuf and hobuf 21.273 + */ 21.274 + if (locc || hocc) 21.275 + { 21.276 + if (locc) 21.277 + FD_SET_rjb(actl, &wrfs); 21.278 + if (hocc) 21.279 + FD_SET_rjb(acth, &wrfs); 21.280 + } 21.281 + else 21.282 + FD_SET_rjb(acto, &rdfs); 21.283 + 21.284 + if (licc) 21.285 + FD_SET_rjb(acto, &wrfs); 21.286 + else 21.287 + FD_SET_rjb(actl, &rdfs); 21.288 + 21.289 + if (hicc) 21.290 + FD_SET_rjb(acto, &wrfs); 21.291 + else 21.292 + FD_SET_rjb(acth, &rdfs); 21.293 + } 21.294 + 21.295 + if (acth == 32 && lish>=0) FD_SET_rjb(lish, &rdfs); 21.296 + if (actg == 32) FD_SET_rjb(lisg, &rdfs); 21.297 + if (actc == 32) FD_SET_rjb(lisc, &rdfs); 21.298 + 21.299 + /* now make exfs the union of the read and write fd sets, plus 21.300 + * "actl" */ 21.301 + { 21.302 + int i; 21.303 + exfs = rdfs; 21.304 + for(i=0; i<32; i++) /* XXX we only copy fd numbers up to 31 */ 21.305 + if (FD_ISSET(i, &wrfs)) 21.306 + FD_SET_rjb(i, &exfs); 21.307 + FD_SET_rjb(actl, &exfs); 21.308 + } 21.309 + 21.310 + /* XXX AND: can't print something of type fd_set as %x - it 21.311 + * might be an array */ 21.312 + DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n", 21.313 + prog_name, rdfs, wrfs, exfs)); 21.314 + 21.315 + if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0) 21.316 + fault("select: %s\n", strerror(errno)); 21.317 + 21.318 + DB(fprintf(stderr, "%s: after select: %08x %08x %08x\n", 21.319 + prog_name, rdfs, wrfs, exfs)); 21.320 + 21.321 + /* XXX it appears that a non-blocking socket may not show up 21.322 + * correctly in exfs but instead goes readable with no data in 21.323 + * it. Thus we check for zero and goto the appropriate close 21.324 + * method. */ 21.325 + 21.326 + /* Deal with exceptions */ 21.327 + if (FD_ISSET_rjb(actg, &exfs)) 21.328 + { 21.329 + exfs_actg: 21.330 + close(actg); 21.331 + gdbmode = FALSE; 21.332 + oicc = 0; 21.333 + oiptr = oibuf; 21.334 + actg = 32; 21.335 + continue; /* because assumptions changed */ 21.336 + } 21.337 + if (FD_ISSET_rjb(acth, &exfs)) 21.338 + { 21.339 + exfs_acth: 21.340 + close(acth); 21.341 + hicc = hocc = 0; 21.342 + hiptr = hibuf; 21.343 + hoptr = hibuf; 21.344 + acth = 32; 21.345 + continue; /* because assumptions changed */ 21.346 + } 21.347 + if (FD_ISSET_rjb(actl, &exfs) || 21.348 + FD_ISSET_rjb(acto, &exfs)) 21.349 + { 21.350 + exfs_actl: 21.351 + exfs_acto: 21.352 + /* Thats all folks ... */ 21.353 + break; 21.354 + } 21.355 + if (FD_ISSET_rjb(actc, &exfs)) 21.356 + { 21.357 + exfs_ctl: 21.358 + close(actc); 21.359 + actc = 32; 21.360 + ctlcc = 0; 21.361 + continue; 21.362 + } 21.363 + 21.364 + /* Deal with reading */ 21.365 + if (FD_ISSET_rjb(acto, &rdfs)) 21.366 + { 21.367 + if ((oicc = read(acto, oiptr = oibuf, MAXSIZE)) < 0) 21.368 + fault("read acto: %d: %s\n", oicc, strerror(errno)); 21.369 + if (!oicc) goto exfs_acto; 21.370 + 21.371 + if (!gdbmode) 21.372 + { 21.373 + int t; 21.374 + 21.375 + assert((locc == 0) && (hocc == 0)); 21.376 + loptr = lobuf; 21.377 + hoptr = hobuf; 21.378 + 21.379 + if (lish>=0) { 21.380 + for(t=0; t<oicc; t++) 21.381 + if (oibuf[t] & 0x80) 21.382 + hobuf[hocc++] = oibuf[t] & 0x7f; 21.383 + else 21.384 + lobuf[locc++] = oibuf[t]; 21.385 + } else { 21.386 + for (t=0; t<oicc; t++) 21.387 + lobuf[locc++] = oibuf[t]; 21.388 + } 21.389 + /* If no high connection scratch that */ 21.390 + if (acth == 32) 21.391 + hocc=0; 21.392 + } 21.393 + } 21.394 + if (FD_ISSET_rjb(actl, &rdfs)) 21.395 + { 21.396 + if ((licc = read(actl, liptr = libuf, MAXSIZE)) < 0) 21.397 + fault("read actl: %d: %s\n", licc, strerror(errno)); 21.398 + if (!licc) goto exfs_actl; 21.399 + } 21.400 + if (FD_ISSET_rjb(acth, &rdfs)) 21.401 + { 21.402 + int t; 21.403 + 21.404 + if ((hicc = read(acth, hiptr = hibuf, MAXSIZE)) < 0) 21.405 + fault("read acth: %d: %s\n", hicc, strerror(errno)); 21.406 + if (!hicc) goto exfs_acth; 21.407 + for(t=0; t<hicc; t++) 21.408 + hibuf[t] |= 0x80; 21.409 + } 21.410 + if (FD_ISSET_rjb(actg, &rdfs)) 21.411 + { 21.412 + if ((gicc = read(actg, giptr = gibuf, MAXSIZE)) < 0) 21.413 + fault("read actg: %d: %s\n", gicc, strerror(errno)); 21.414 + if (debug) write(1, giptr, gicc); /* XXX */ 21.415 + if (!gicc) goto exfs_actg; 21.416 + } 21.417 + if (FD_ISSET_rjb(actc, &rdfs)) 21.418 + { 21.419 + if ((ctlcc = read(actc, ctlbuf, MAXSIZE)) < 0) 21.420 + fault("read actc: %d: %s\n", ctlcc, strerror(errno)); 21.421 + if (debug) write(1, ctlbuf, gicc); 21.422 + if (!ctlcc) goto exfs_ctl; 21.423 + if (ctlbuf[0] == 'r') /* reset command */ 21.424 + { 21.425 + syslog(LOG_INFO, "reset command read, exiting"); 21.426 + if (debug) write(1, "reseting\n", sizeof("reseting\n")); 21.427 + break; 21.428 + } 21.429 + } 21.430 + 21.431 + /* Deal with writing */ 21.432 + if (FD_ISSET_rjb(actg, &wrfs)) 21.433 + { 21.434 + /* We must be in gdb mode so send oi buffer data */ 21.435 + assert(gdbmode); 21.436 + if (debug) write(2, oiptr, oicc); /* XXX */ 21.437 + if ((rc = write(actg, oiptr, oicc)) <= 0) 21.438 + fault("write actg: %d: %s\n", rc, strerror(errno)); 21.439 + oiptr += rc; 21.440 + oicc -= rc; 21.441 + } 21.442 + if (FD_ISSET_rjb(actl, &wrfs)) 21.443 + { 21.444 + if ((rc = write(actl, loptr, locc)) <= 0) 21.445 + fault("write actl: %d: %s\n", rc, strerror(errno)); 21.446 + loptr += rc; 21.447 + locc -= rc; 21.448 + } 21.449 + if (FD_ISSET_rjb(acth, &wrfs)) 21.450 + { 21.451 + if ((rc = write(acth, hoptr, hocc)) <= 0) 21.452 + fault("write acth: %d: %s\n", rc, strerror(errno)); 21.453 + hoptr += rc; 21.454 + hocc -= rc; 21.455 + } 21.456 + if (FD_ISSET_rjb(acto, &wrfs)) 21.457 + { 21.458 + /* If in gdb mode send gdb input, otherwise send low data 21.459 + preferentially */ 21.460 + if (gdbmode) 21.461 + { 21.462 + assert(gicc); 21.463 + if ((rc = write(acto, giptr, gicc)) <= 0) 21.464 + fault("write acto: %d: %s\n", rc, strerror(errno)); 21.465 + giptr += rc; 21.466 + gicc -= rc; 21.467 + } 21.468 + else 21.469 + { 21.470 + if (licc) 21.471 + { 21.472 + if ((rc = write(acto, liptr, licc)) <= 0) 21.473 + fault("write acto: %d: %s\n", rc, strerror(errno)); 21.474 + liptr += rc; 21.475 + licc -= rc; 21.476 + } 21.477 + else 21.478 + { 21.479 + assert(hicc); 21.480 + if ((rc = write(acto, hiptr, hicc)) <= 0) 21.481 + fault("write acto: %d: %s\n", rc, strerror(errno)); 21.482 + hiptr += rc; 21.483 + hicc -= rc; 21.484 + } 21.485 + } 21.486 + } 21.487 + 21.488 + /* Deals with new connections */ 21.489 + if ((acth == 32) && lish>=0 && (FD_ISSET_rjb(lish, &rdfs))) 21.490 + { 21.491 + fromlen = sizeof(from); 21.492 + if ((acth = accept(lish, &from, &fromlen)) < 0) 21.493 + { 21.494 + syslog(LOG_WARNING, "accept: %m"); 21.495 + acth = 32; 21.496 + } 21.497 + else 21.498 + { 21.499 + noblock(acth); 21.500 + hicc = hocc = 0; 21.501 + syslog(LOG_INFO, "highbit client peer is %s:%u\n", 21.502 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 21.503 + } 21.504 + } 21.505 + 21.506 + if ((actg == 32) && (FD_ISSET_rjb(lisg, &rdfs))) 21.507 + { 21.508 + fromlen = sizeof(from); 21.509 + if ((actg = accept(lisg, &from, &fromlen)) < 0) 21.510 + { 21.511 + syslog(LOG_WARNING, "accept: %m"); 21.512 + actg = 32; 21.513 + } 21.514 + else 21.515 + { 21.516 + noblock(actg); 21.517 + gicc = 0; 21.518 + gdbmode = TRUE; 21.519 + syslog(LOG_INFO, "gdb client peer is %s:%u\n", 21.520 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 21.521 + } 21.522 + } 21.523 + 21.524 + if ((actc == 32) && (FD_ISSET_rjb(lisc, &rdfs))) 21.525 + { 21.526 + fromlen = sizeof(from); 21.527 + if ((actc = accept(lisc, &from, &fromlen)) < 0) 21.528 + { 21.529 + syslog(LOG_WARNING, "accept (ctl): %m"); 21.530 + actc = 32; 21.531 + } 21.532 + else 21.533 + { 21.534 + noblock(actc); 21.535 + syslog(LOG_INFO, "ctl client peer is %s:%u\n", 21.536 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 21.537 + } 21.538 + } 21.539 + 21.540 + /* Back to top of loop */ 21.541 + } 21.542 + 21.543 + /* We are bailing because one of the primary connections has gone 21.544 + * away. We close these all explicitly here because that way the 21.545 + * timeout on reusing the port numbers is smnaller. */ 21.546 + 21.547 + close(acth); 21.548 + close(actg); 21.549 + /* XXX AND: why are we closing all these "character counts" ?? */ 21.550 + close(gicc); 21.551 + close(oicc); 21.552 + close(licc); 21.553 + close(locc); 21.554 + close(hicc); 21.555 + close(hocc); 21.556 +} 21.557 + 21.558 +/* 21.559 + * ------------------------------------------------------------ 21.560 + */ 21.561 +int main(int argc, char **argv) 21.562 +{ 21.563 + /* In general, suffix "l" is low channel, "h" is high channel, "g" 21.564 + * is gdb channel, "c" is control channel and "o" is output channel. 21.565 + */ 21.566 + struct sockaddr_in from; 21.567 + int infd = 0, outfd; 21.568 + unsigned short portl, porth, portg, portc, porto; 21.569 + int on = 1, c; 21.570 + char *outname, *outservice; 21.571 + int fromlen; 21.572 + int lish, lisg, lisc; 21.573 +#if 0 21.574 + FILE *newerr; 21.575 +#endif /* 0 */ 21.576 + 21.577 + prog_name = argv[0]; 21.578 + 21.579 + if (isatty(infd)) 21.580 + usage(); 21.581 + 21.582 + /* Here, then not just a simple idiot. */ 21.583 + 21.584 + signal(SIGPIPE, SIG_IGN); 21.585 + 21.586 + openlog(prog_name, LOG_PID, LOG_DAEMON); 21.587 + 21.588 + fromlen = sizeof(from); 21.589 + if (getsockname(infd, &from, &fromlen) < 0) 21.590 + fault("getsockname: %s", strerror(errno)); 21.591 + if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET)) 21.592 + fault("not an inet socket (family=%d)\n", from.sin_family); 21.593 + 21.594 + portl = ntohs(from.sin_port); 21.595 + porth = portl+1; 21.596 + portg = porth+1; 21.597 + portc = portg+1; 21.598 + 21.599 + fromlen = sizeof(from); 21.600 + if (getpeername(infd, &from, &fromlen) < 0) 21.601 + fault("getpeername: %s", strerror(errno)); 21.602 + if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET)) 21.603 + fault("not an inet socket (family=%d)\n", from.sin_family); 21.604 + 21.605 + syslog(LOG_INFO, "on port %u peer is %s:%u\n", portl, 21.606 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 21.607 + 21.608 + if (setsockopt(infd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 21.609 + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 21.610 + 21.611 + /* from here on, we map stderr to output on the connection so we can 21.612 + * report errors to the remote user. 21.613 + */ 21.614 +#if 0 21.615 + if (!(newerr = fdopen(infd, "w"))) 21.616 + syslog(LOG_WARNING, "fdopen: %m"); 21.617 + else 21.618 + *stderr = *newerr; 21.619 +#endif 21.620 + 21.621 + while((c = getopt(argc, argv, "d8h:g:c:")) != EOF) 21.622 + { 21.623 + switch(c) 21.624 + { 21.625 + case 'd': 21.626 + debug++; 21.627 + break; 21.628 + 21.629 + case 'h': 21.630 + /* high bit port */ 21.631 + if (getservice(optarg, &porth) < 0) 21.632 + fault("getservice failed (high port '%s')\n", optarg); 21.633 + break; 21.634 + 21.635 + case 'g': 21.636 + /* gdb port */ 21.637 + if (getservice(optarg, &portg) < 0) 21.638 + fault("getservice failed (gdb port '%s')\n", optarg); 21.639 + break; 21.640 + 21.641 + case 'c': 21.642 + /* control port */ 21.643 + if (getservice(optarg, &portc) < 0) 21.644 + fault("getservice failed (control port '%s')\n", optarg); 21.645 + break; 21.646 + 21.647 + case '8': 21.648 + /* 8-bit clean; no high port */ 21.649 + porth=0; 21.650 + break; 21.651 + 21.652 + default: 21.653 + fault("bad argument list!\n"); 21.654 + } 21.655 + } 21.656 + 21.657 + if (argc != optind + 1) 21.658 + fault("unparsed arguments (%d!=%d)\n", argc, optind+1); 21.659 + 21.660 + outname = argv[optind]; 21.661 + if (!(outservice = strchr(outname, ':'))) 21.662 + fault("output arg '%s' doesn't contain ':'\n", outname); 21.663 + *outservice++ = 0; 21.664 + if (getservice(outservice, &porto) < 0) 21.665 + fault("getservice failed (output port '%s')\n", outservice); 21.666 + 21.667 + /* Time to start the sockets */ 21.668 + 21.669 + if (porth) { 21.670 + lish = startlistening(porth); 21.671 + } else { 21.672 + lish = -1; 21.673 + } 21.674 + lisg = startlistening(portg); 21.675 + lisc = startlistening(portc); 21.676 + 21.677 + outfd = connect_host(outname, porto); 21.678 + 21.679 + doit(infd, outfd, lish, lisg, lisc); 21.680 + 21.681 + syslog(LOG_INFO, "terminating normally\n"); 21.682 + 21.683 + fclose(stderr); 21.684 + 21.685 + closelog(); 21.686 + exit(0); 21.687 +} 21.688 + 21.689 +/* End $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ */
22.1 --- a/tools/python/xen/xend/XendClient.py Tue Jul 06 17:25:40 2004 +0000 22.2 +++ b/tools/python/xen/xend/XendClient.py Tue Jul 06 17:27:27 2004 +0000 22.3 @@ -1,6 +1,11 @@ 22.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 22.5 """Client API for the HTTP interface on xend. 22.6 Callable as a script - see main(). 22.7 + 22.8 +This API is the 'control-plane' for xend. 22.9 +The 'data-plane' is done separately. For example, consoles 22.10 +are accessed via sockets on xend, but the list of consoles 22.11 +is accessible via this API. 22.12 """ 22.13 import sys 22.14 import httplib 22.15 @@ -27,6 +32,8 @@ class Foo(httplib.HTTPResponse): 22.16 22.17 22.18 def sxprio(sxpr): 22.19 + """Convert an sxpr to a string. 22.20 + """ 22.21 io = StringIO() 22.22 sxp.show(sxpr, out=io) 22.23 print >> io 22.24 @@ -80,6 +87,12 @@ def eventurl(location, root, id=''): 22.25 return urljoin(location, root, 'event/', id) 22.26 22.27 def xend_request(url, method, data=None): 22.28 + """Make a request to xend. 22.29 + 22.30 + url xend request url 22.31 + method http method: POST or GET 22.32 + data request argument data (dict) 22.33 + """ 22.34 urlinfo = urlparse.urlparse(url) 22.35 (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo 22.36 if DEBUG: print url, urlinfo 22.37 @@ -122,20 +135,37 @@ def xend_request(url, method, data=None) 22.38 return val 22.39 22.40 def xend_get(url, args=None): 22.41 + """Make a xend request using GET. 22.42 + Requests using GET are 'safe' and may be repeated without 22.43 + nasty side-effects. 22.44 + """ 22.45 return xend_request(url, "GET", args) 22.46 22.47 def xend_call(url, data): 22.48 + """Make xend request using POST. 22.49 + Requests using POST potentially cause side-effects and should 22.50 + not be repeated unless it really is wanted to do the side 22.51 + effect again. 22.52 + """ 22.53 return xend_request(url, "POST", data) 22.54 22.55 class Xend: 22.56 22.57 + """Default location of the xend server.""" 22.58 SRV_DEFAULT = "localhost:8000" 22.59 + 22.60 + """Default path to the xend root on the server.""" 22.61 ROOT_DEFAULT = "/xend/" 22.62 22.63 def __init__(self, srv=None, root=None): 22.64 self.bind(srv, root) 22.65 22.66 def bind(self, srv=None, root=None): 22.67 + """Bind to a given server. 22.68 + 22.69 + srv server location (host:port) 22.70 + root server xend root path 22.71 + """ 22.72 if srv is None: srv = self.SRV_DEFAULT 22.73 if root is None: root = self.ROOT_DEFAULT 22.74 if not root.endswith('/'): root += '/' 22.75 @@ -195,9 +225,10 @@ class Xend: 22.76 return xend_call(self.domainurl(id), 22.77 {'op' : 'pause'}) 22.78 22.79 - def xend_domain_shutdown(self, id): 22.80 + def xend_domain_shutdown(self, id, reason): 22.81 return xend_call(self.domainurl(id), 22.82 - {'op' : 'shutdown'}) 22.83 + {'op' : 'shutdown', 22.84 + 'reason' : reason }) 22.85 22.86 def xend_domain_destroy(self, id): 22.87 return xend_call(self.domainurl(id),
23.1 --- a/tools/python/xen/xend/XendDomain.py Tue Jul 06 17:25:40 2004 +0000 23.2 +++ b/tools/python/xen/xend/XendDomain.py Tue Jul 06 17:27:27 2004 +0000 23.3 @@ -5,8 +5,11 @@ 23.4 Needs to be persistent for one uptime. 23.5 """ 23.6 import sys 23.7 +import traceback 23.8 23.9 from twisted.internet import defer 23.10 +defer.Deferred.debug = 1 23.11 +from twisted.internet import reactor 23.12 23.13 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() 23.14 23.15 @@ -28,10 +31,19 @@ eserver = EventServer.instance() 23.16 class XendDomain: 23.17 """Index of all domains. Singleton. 23.18 """ 23.19 - 23.20 + 23.21 + """Path to domain database.""" 23.22 dbpath = "domain" 23.23 + 23.24 + """Table of domain info indexed by domain id.""" 23.25 domain = {} 23.26 23.27 + """Table of configs for domain restart, indexed by domain id.""" 23.28 + restarts = {} 23.29 + 23.30 + """Table of delayed calls.""" 23.31 + schedule = {} 23.32 + 23.33 def __init__(self): 23.34 self.xconsole = XendConsole.instance() 23.35 # Table of domain info indexed by domain id. 23.36 @@ -49,6 +61,53 @@ class XendDomain: 23.37 print 'XendDomain> virq', val 23.38 self.reap() 23.39 23.40 + def schedule_later(self, _delay, _name, _fn, *args): 23.41 + """Schedule a function to be called later (if not already scheduled). 23.42 + 23.43 + _delay delay in seconds 23.44 + _name schedule name 23.45 + _fn function 23.46 + args arguments 23.47 + """ 23.48 + if self.schedule.get(_name): return 23.49 + self.schedule[_name] = reactor.callLater(_delay, _fn, *args) 23.50 + 23.51 + def schedule_cancel(self, name): 23.52 + """Cancel a scheduled function call. 23.53 + 23.54 + name schedule name to cancel 23.55 + """ 23.56 + callid = self.schedule.get(name) 23.57 + if not callid: 23.58 + return 23.59 + if callid.active(): 23.60 + callid.cancel() 23.61 + del self.schedule[name] 23.62 + 23.63 + def reap_schedule(self, delay=0): 23.64 + """Schedule reap to be called later. 23.65 + 23.66 + delay delay in seconds 23.67 + """ 23.68 + self.schedule_later(delay, 'reap', self.reap) 23.69 + 23.70 + def reap_cancel(self): 23.71 + """Cancel any scheduled reap. 23.72 + """ 23.73 + self.schedule_cancel('reap') 23.74 + 23.75 + def refresh_schedule(self, delay=0): 23.76 + """Schedule refresh to be called later. 23.77 + 23.78 + delay delay in seconds 23.79 + """ 23.80 + self.schedule_later(delay, 'refresh', self.refresh) 23.81 + 23.82 + def refresh_cancel(self): 23.83 + """Cancel any scheduled refresh. 23.84 + """ 23.85 + self.schedule_cancel('refresh') 23.86 + 23.87 def rm_all(self): 23.88 """Remove all domain info. Used after reboot. 23.89 """ 23.90 @@ -145,6 +204,7 @@ class XendDomain: 23.91 """Look for domains that have crashed or stopped. 23.92 Tidy them up. 23.93 """ 23.94 + self.reap_cancel() 23.95 print 'XendDomain>reap>' 23.96 domlist = xc.domain_getinfo() 23.97 casualties = [] 23.98 @@ -158,12 +218,14 @@ class XendDomain: 23.99 for d in casualties: 23.100 id = str(d['dom']) 23.101 print 'XendDomain>reap> died id=', id, d 23.102 - self.domain_destroy(id, refresh=0) 23.103 + self.final_domain_destroy(id) 23.104 print 'XendDomain>reap<' 23.105 23.106 def refresh(self): 23.107 """Refresh domain list from Xen. 23.108 """ 23.109 + self.refresh_cancel() 23.110 + print 'XendDomain>refresh>' 23.111 domlist = xc.domain_getinfo() 23.112 # Index the domlist by id. 23.113 # Add entries for any domains we don't know about. 23.114 @@ -184,7 +246,7 @@ class XendDomain: 23.115 d.update(dominfo) 23.116 else: 23.117 self._delete_domain(d.id) 23.118 - self.reap() 23.119 + self.reap_schedule(1) 23.120 23.121 def refresh_domain(self, id): 23.122 """Refresh information for a single domain. 23.123 @@ -267,21 +329,70 @@ class XendDomain: 23.124 """Shutdown domain (nicely). 23.125 23.126 id domain id 23.127 - reason shutdown type: poweroff, reboot, halt 23.128 + reason shutdown type: poweroff, reboot, suspend, halt 23.129 """ 23.130 dom = int(id) 23.131 if dom <= 0: 23.132 return 0 23.133 + self.domain_restart_schedule(id, reason) 23.134 eserver.inject('xend.domain.shutdown', [id, reason]) 23.135 + if reason == 'halt': 23.136 + reason = 'poweroff' 23.137 val = xend.domain_shutdown(dom, reason) 23.138 - self.refresh() 23.139 + self.refresh_schedule() 23.140 return val 23.141 - 23.142 - def domain_destroy(self, id, refresh=1): 23.143 - """Terminate domain immediately. 23.144 + 23.145 + def domain_restart_schedule(self, id, reason): 23.146 + """Schedule a restart for a domain if it needs one. 23.147 + 23.148 + id domain id 23.149 + reason shutdown reason 23.150 + """ 23.151 + if id in self.restarts: 23.152 + # Don't schedule if already there. 23.153 + return 23.154 + restart = 0 23.155 + if reason in ['poweroff', 'reboot']: 23.156 + dominfo = self.domain.get(id) 23.157 + if dominfo and (dominfo.autorestart or reason == 'reboot'): 23.158 + restart = 1 23.159 + # Clear autorestart flag to avoid multiple restarts. 23.160 + dominfo.autorestart = 0 23.161 + 23.162 + if restart: 23.163 + self.restarts[id] = dominfo.config 23.164 + 23.165 + def domain_restart_cancel(self, id): 23.166 + """Cancel any restart scheduled for a domain. 23.167 23.168 id domain id 23.169 - refresh send a domain destroy event if true 23.170 + """ 23.171 + dominfo = self.domain.get(id) 23.172 + if dominfo: 23.173 + dominfo.autorestart = 0 23.174 + if id in self.restarts: 23.175 + del self.restarts[id] 23.176 + 23.177 + def domain_restarts(self): 23.178 + """Execute any scheduled domain restarts for domains that have gone. 23.179 + """ 23.180 + for id in self.restarts.keys(): 23.181 + if id in self.domain: 23.182 + # Don't execute restart for domains still running. 23.183 + continue 23.184 + config = self.restarts[id] 23.185 + # Remove it from the restarts. 23.186 + del self.restarts[id] 23.187 + try: 23.188 + self.domain_create(config) 23.189 + except: 23.190 + print >>sys.stderr, "XendDomain> Exception restarting domain" 23.191 + traceback.print_exc(sys.stderr) 23.192 + 23.193 + def final_domain_destroy(self, id): 23.194 + """Final destruction of a domain.. 23.195 + 23.196 + id domain id 23.197 """ 23.198 dom = int(id) 23.199 if dom <= 0: 23.200 @@ -292,15 +403,26 @@ class XendDomain: 23.201 val = dominfo.destroy() 23.202 else: 23.203 val = xc.domain_destroy(dom=dom) 23.204 - if refresh: self.refresh() 23.205 return val 23.206 23.207 + def domain_destroy(self, id): 23.208 + """Terminate domain immediately. 23.209 + Camcels any restart for the domain. 23.210 + 23.211 + id domain id 23.212 + """ 23.213 + self.domain_restart_cancel(id) 23.214 + val = self.final_domain_destroy(id) 23.215 + self.refresh_schedule() 23.216 + return val 23.217 + 23.218 def domain_migrate(self, id, dst): 23.219 """Start domain migration. 23.220 23.221 id domain id 23.222 """ 23.223 # Need a cancel too? 23.224 + # Don't forget to cancel restart for it. 23.225 pass 23.226 23.227 def domain_save(self, id, dst, progress=0):
24.1 --- a/tools/python/xen/xend/XendDomainInfo.py Tue Jul 06 17:25:40 2004 +0000 24.2 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Jul 06 17:27:27 2004 +0000 24.3 @@ -15,6 +15,7 @@ import sys 24.4 import os 24.5 24.6 from twisted.internet import defer 24.7 +defer.Deferred.debug = 1 24.8 24.9 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() 24.10 import xen.util.ip 24.11 @@ -291,6 +292,9 @@ def vm_restore(src, progress=0): 24.12 if dom < 0: 24.13 raise VmError('restore failed') 24.14 vmconfig = sxp.from_string(d['vmconfig']) 24.15 + if not vmconfig: 24.16 + raise VmError('bad vmconfig s-expression') 24.17 + vmconfig = vmconfig[0] 24.18 vm.config = sxp.child_value(vmconfig, 'config') 24.19 deferred = vm.dom_configure(dom) 24.20 def vifs_cb(val, vm): 24.21 @@ -362,6 +366,8 @@ class XendDomainInfo: 24.22 self.state = self.STATE_OK 24.23 #todo: set to migrate info if migrating 24.24 self.migrate = None 24.25 + #Whether to auto-restart 24.26 + self.autorestart = 0 24.27 24.28 def setdom(self, dom): 24.29 self.dom = int(dom) 24.30 @@ -417,7 +423,9 @@ class XendDomainInfo: 24.31 self.config = config 24.32 try: 24.33 self.name = sxp.child_value(config, 'name') 24.34 - self.memory = int(sxp.child_value(config, 'memory', '128')) 24.35 + self.memory = int(sxp.child_value(config, 'memory') or '128') 24.36 + if sxp.child(config, 'autorestart'): 24.37 + self.autorestart = 1 24.38 self.configure_backends() 24.39 image = sxp.child_value(config, 'image') 24.40 image_name = sxp.name(image) 24.41 @@ -426,14 +434,18 @@ class XendDomainInfo: 24.42 raise VmError('unknown image type: ' + image_name) 24.43 image_handler(self, image) 24.44 deferred = self.configure() 24.45 + def cbok(x): 24.46 + print 'vm_create> cbok', x 24.47 + return x 24.48 + def cberr(err): 24.49 + self.destroy() 24.50 + return err 24.51 + deferred.addCallback(cbok) 24.52 + deferred.addErrback(cberr) 24.53 except StandardError, ex: 24.54 # Catch errors, cleanup and re-raise. 24.55 self.destroy() 24.56 raise 24.57 - def cbok(x): 24.58 - print 'vm_create> cbok', x 24.59 - return x 24.60 - deferred.addCallback(cbok) 24.61 print 'vm_create<' 24.62 return deferred 24.63 24.64 @@ -445,7 +457,7 @@ class XendDomainInfo: 24.65 """ 24.66 devices = [] 24.67 for d in sxp.children(self.config, 'device'): 24.68 - dev = sxp.child0(d) 24.69 + dev = sxp.child(d) 24.70 if dev is None: continue 24.71 if name == sxp.name(dev): 24.72 devices.append(dev) 24.73 @@ -576,7 +588,7 @@ class XendDomainInfo: 24.74 if self.recreate: return 24.75 memory = self.memory 24.76 name = self.name 24.77 - cpu = int(sxp.child_value(self.config, 'cpu', '-1')) 24.78 + cpu = int(sxp.child_value(self.config, 'cpu') or '-1') 24.79 print 'init_domain>', memory, name, cpu 24.80 dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu) 24.81 if dom <= 0: 24.82 @@ -641,7 +653,7 @@ class XendDomainInfo: 24.83 devices = sxp.children(self.config, 'device') 24.84 index = {} 24.85 for d in devices: 24.86 - dev = sxp.child0(d) 24.87 + dev = sxp.child(d) 24.88 if dev is None: 24.89 raise VmError('invalid device') 24.90 dev_name = sxp.name(dev) 24.91 @@ -660,7 +672,7 @@ class XendDomainInfo: 24.92 """Set configuration flags if the vm is a backend for netif of blkif. 24.93 """ 24.94 for c in sxp.children(self.config, 'backend'): 24.95 - name = sxp.name(sxp.child0(c)) 24.96 + name = sxp.name(sxp.child(c)) 24.97 if name == 'blkif': 24.98 self.blkif_backend = 1 24.99 elif name == 'netif': 24.100 @@ -706,6 +718,10 @@ class XendDomainInfo: 24.101 self.name = d['name'] 24.102 self.memory = d['memory']/1024 24.103 deferred = self.configure() 24.104 + def cberr(err): 24.105 + self.destroy() 24.106 + return err 24.107 + deferred.addErrback(cberr) 24.108 except StandardError, ex: 24.109 self.destroy() 24.110 raise 24.111 @@ -738,7 +754,7 @@ def vm_image_linux(vm, image): 24.112 """ 24.113 kernel = sxp.child_value(image, "kernel") 24.114 cmdline = "" 24.115 - ip = sxp.child_value(image, "ip", "dhcp") 24.116 + ip = sxp.child_value(image, "ip") or "dhcp" 24.117 if ip: 24.118 cmdline += " ip=" + ip 24.119 root = sxp.child_value(image, "root") 24.120 @@ -747,7 +763,7 @@ def vm_image_linux(vm, image): 24.121 args = sxp.child_value(image, "args") 24.122 if args: 24.123 cmdline += " " + args 24.124 - ramdisk = sxp.child_value(image, "ramdisk", '') 24.125 + ramdisk = sxp.child_value(image, "ramdisk") or '' 24.126 vifs = vm.config_devices("vif") 24.127 vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs)) 24.128 return vm 24.129 @@ -764,7 +780,7 @@ def vm_image_netbsd(vm, image): 24.130 #todo: Same as for linux. Is that right? If so can unify them. 24.131 kernel = sxp.child_value(image, "kernel") 24.132 cmdline = "" 24.133 - ip = sxp.child_value(image, "ip", "dhcp") 24.134 + ip = sxp.child_value(image, "ip") or "dhcp" 24.135 if ip: 24.136 cmdline += "ip=" + ip 24.137 root = sxp.child_value(image, "root") 24.138 @@ -793,7 +809,7 @@ def vm_dev_vif(vm, val, index): 24.139 defer = make_vif(vm.dom, vif, vmac, vm.recreate) 24.140 def fn(id): 24.141 dev = xend.netif_dev(vm.dom, vif) 24.142 - devid = sxp.attribute(val, 'id') 24.143 + devid = sxp.child_value(val, 'id') 24.144 if devid: 24.145 dev.setprop('id', devid) 24.146 bridge = sxp.child_value(val, "bridge") 24.147 @@ -820,7 +836,7 @@ def vm_dev_vbd(vm, val, index): 24.148 dev = sxp.child_value(val, 'dev') 24.149 if not dev: 24.150 raise VmError('vbd: Missing dev') 24.151 - mode = sxp.child_value(val, 'mode', 'r') 24.152 + mode = sxp.child_value(val, 'mode') or 'r' 24.153 defer = make_disk(vm.dom, uname, dev, mode, vm.recreate) 24.154 def fn(vbd): 24.155 dev = xend.blkif_dev(vm.dom, vdev) 24.156 @@ -922,7 +938,7 @@ def vm_field_vnet(vm, config, val, index 24.157 if id is None: 24.158 raise VmError('vnet: missing vif id') 24.159 dev = vm.get_device_by_id('vif', id) 24.160 - #vnet = sxp.child_value(v, 'vnet', 1) 24.161 + #vnet = sxp.child_value(v, 'vnet') or '1' 24.162 #mac = sxp.child_value(dev, 'mac') 24.163 #vif = sxp.child_value(dev, 'vif') 24.164 #vnet_bridge(vnet, mac, vm.dom, 0)
25.1 --- a/tools/python/xen/xend/XendMigrate.py Tue Jul 06 17:25:40 2004 +0000 25.2 +++ b/tools/python/xen/xend/XendMigrate.py Tue Jul 06 17:27:27 2004 +0000 25.3 @@ -2,22 +2,125 @@ 25.4 25.5 import sys 25.6 import socket 25.7 +import time 25.8 + 25.9 +from twisted.internet import reactor 25.10 +from twisted.internet import defer 25.11 +defer.Deferred.debug = 1 25.12 +from twisted.internet.protocol import Protocol 25.13 +from twisted.internet.protocol import ClientFactory 25.14 25.15 import sxp 25.16 import XendDB 25.17 import EventServer; eserver = EventServer.instance() 25.18 25.19 +from xen.xend.packing import SxpPacker, SxpUnpacker 25.20 +from xen.xend import XendDomain 25.21 +xd = XendDomain.instance() 25.22 + 25.23 + 25.24 +XFRD_PORT = 8002 25.25 + 25.26 +XFR_PROTO_MAJOR = 1 25.27 +XFR_PROTO_MINOR = 0 25.28 + 25.29 +class Migrate(Protocol): 25.30 + 25.31 + def __init__(self, minfo): 25.32 + self.packer = None 25.33 + self.unpacker = None 25.34 + self.minfo = minfo 25.35 + 25.36 + def connectionMade(self): 25.37 + self.packer = SxpPacker(self.transport) 25.38 + self.unpacker = SxpPacker() 25.39 + # Send hello. 25.40 + self.packer.pack(['xfr.hello', XFR_PROTO_MAJOR, XFR_PROTO_MINOR]) 25.41 + # Send migrate. 25.42 + vmconfig = self.minfo.vmconfig() 25.43 + if not vmconfig: 25.44 + self.loseConnection() 25.45 + return 25.46 + self.packer.pack(['xfr.migrate', 25.47 + self.minfo.src_dom, 25.48 + vmconfig, 25.49 + self.minfo.dst_host, 25.50 + self.minfo.dst_port]) 25.51 + 25.52 + def connectionLost(self, reason): 25.53 + self.minfo.closed(reason) 25.54 + 25.55 + def dataReceived(self, data): 25.56 + try: 25.57 + self.unpacker.reset(data) 25.58 + val = self.unpacker.unpack() 25.59 + print 'dataReceived>', 'val=', val 25.60 + op = val[0] 25.61 + op.replace('.', '_') 25.62 + if op.startwith('xfr_'): 25.63 + fn = getattr(self, op, self.unknown) 25.64 + else: 25.65 + fn = self.unknown 25.66 + fn(val) 25.67 + except Exception, ex: 25.68 + print 'dataReceived>', ex 25.69 + pass 25.70 + 25.71 + def unknown(self, val): 25.72 + print 'unknown>', val 25.73 + 25.74 + def xfr_progress(self, val): 25.75 + print 'xfr_progress>', val 25.76 + 25.77 + def xfr_error(self, val): 25.78 + # If we get an error with non-zero code the migrate failed. 25.79 + # An error with code zero indicates hello success. 25.80 + err = int(val[1]) 25.81 + if not err: return 25.82 + self.minfo.error(err); 25.83 + self.loseConnection() 25.84 + 25.85 + def xfr_ok(self, val): 25.86 + # An ok indicates migrate completed successfully, and contains 25.87 + # the new domain id on the remote system. 25.88 + dom = int(val[1]) 25.89 + self.minfo.ok(dom) 25.90 + self.loseConnection() 25.91 + 25.92 +class MigrateClientFactory(ClientFactory): 25.93 + 25.94 + def __init__(self, minfo): 25.95 + ClientFactory.__init__(self) 25.96 + self.minfo = minfo 25.97 + 25.98 + def startedConnecting(self, connector): 25.99 + print 'Started to connect', 'self=', self, 'connector=', connector 25.100 + 25.101 + def buildProtocol(self, addr): 25.102 + print 'buildProtocol>', addr 25.103 + return Migrate(self.minfo) 25.104 + 25.105 + def clientConnectionLost(self, connector, reason): 25.106 + print 'clientConnectionLost>', 'connector=', connector, 'reason=', reason 25.107 + 25.108 + def clientConnectionFailed(self, connector, reason): 25.109 + print 'clientConnectionFailed>', 'connector=', connector, 'reason=', reason 25.110 + 25.111 + 25.112 class XendMigrateInfo: 25.113 25.114 # states: begin, active, failed, succeeded? 25.115 25.116 - def __init__(self, id, dom, dst): 25.117 + def __init__(self, id, dom, host, port): 25.118 self.id = id 25.119 self.state = 'begin' 25.120 self.src_host = socket.gethostname() 25.121 self.src_dom = dom 25.122 self.dst_host = dst 25.123 + self.dst_port = port 25.124 self.dst_dom = None 25.125 + self.start = 0 25.126 + self.deferred = defer.Deferred() 25.127 25.128 def set_state(self, state): 25.129 self.state = state 25.130 @@ -29,12 +132,33 @@ class XendMigrateInfo: 25.131 sxpr = ['migrate', ['id', self.id], ['state', self.state] ] 25.132 sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ] 25.133 sxpr.append(sxpr_src) 25.134 - sxpr_dst = ['dst', ['host', self.dst] ] 25.135 + sxpr_dst = ['dst', ['host', self.dst_host] ] 25.136 if self.dst_dom: 25.137 sxpr_dst.append(['domain', self.dst_dom]) 25.138 sxpr.append(sxpr_dst) 25.139 return sxpr 25.140 - 25.141 + 25.142 + def vmconfig(self): 25.143 + dominfo = xd.domain_get(self.dom) 25.144 + if dominfo: 25.145 + val = return sxp.to_string(dominfo) 25.146 + else: 25.147 + val = None 25.148 + return None 25.149 + 25.150 + def error(self, err): 25.151 + self.state = 'error' 25.152 + 25.153 + def ok(self, dom): 25.154 + self.state = 'ok' 25.155 + self.dst_dom = dom 25.156 + 25.157 + def close(self): 25.158 + if self.state =='ok': 25.159 + eserver.inject('xend.migrate.ok', self.sxpr()) 25.160 + else: 25.161 + self.state = 'error' 25.162 + eserver.inject('xend.migrate.error', self.sxpr()) 25.163 25.164 class XendMigrate: 25.165 # Represents migration in progress. 25.166 @@ -84,15 +208,15 @@ class XendMigrate: 25.167 def migrate_get(self, id): 25.168 return self.migrate.get(id) 25.169 25.170 - def migrate_begin(self, dom, dst): 25.171 + def migrate_begin(self, dom, host): 25.172 # Check dom for existence, not migrating already. 25.173 - # Create migrate info, tell xend to migrate it? 25.174 - # - or fork migrate command ourselves? 25.175 # Subscribe to migrate notifications (for updating). 25.176 id = self.nextid() 25.177 - info = XenMigrateInfo(id, dom, dst) 25.178 + info = XenMigrateInfo(id, dom, host, XFRD_PORT) 25.179 self._add_migrate(id, info) 25.180 - return id 25.181 + mcf = MigrateClientFactory(info) 25.182 + reactor.connectTCP('localhost', XFRD_PORT, mcf) 25.183 + return info.deferred 25.184 25.185 def instance(): 25.186 global inst
26.1 --- a/tools/python/xen/xend/XendRoot.py Tue Jul 06 17:25:40 2004 +0000 26.2 +++ b/tools/python/xen/xend/XendRoot.py Tue Jul 06 17:27:27 2004 +0000 26.3 @@ -145,7 +145,7 @@ class XendRoot: 26.4 val default value (optional, defaults to None) 26.5 returns value 26.6 """ 26.7 - return sxp.child_value(self.config, name, val=val) 26.8 + return sxp.child_value(self.config, name) or val 26.9 26.10 def instance(): 26.11 global inst
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/tools/python/xen/xend/packing.py Tue Jul 06 17:27:27 2004 +0000 27.3 @@ -0,0 +1,329 @@ 27.4 + 27.5 +# XDR-style packer/unpacker for sxpr. 27.6 +# 27.7 +# string -> [STRING] [len:u16] <len bytes> 27.8 +# atom -> [ATOM] [len:u16] <len bytes> 27.9 +# int -> [UINT] [value] 27.10 +# list -> [LIST] {1 elt}* 0 27.11 +# null -> [NULL] 27.12 +# none -> [NONE] 27.13 +# bool -> [BOOL] { 0:u8 | 1:u8 } 27.14 +# 27.15 +# types packed as u16. 27.16 +# 27.17 +# So (a b c) -> [LIST] 1 a 1 b 1 c 0 27.18 +# () -> [LIST] 0 27.19 + 27.20 +import struct 27.21 + 27.22 +try: 27.23 + from cStringIO import StringIO as _StringIO 27.24 +except ImportError: 27.25 + from StringIO import StringIO as _StringIO 27.26 + 27.27 +import types 27.28 + 27.29 +class Error(Exception): 27.30 + 27.31 + def __init__(self, msg): 27.32 + self.msg = msg 27.33 + 27.34 + def __repr__(self): 27.35 + return repr(self.msg) 27.36 + 27.37 + def __str__(self): 27.38 + return str(self.msg) 27.39 + 27.40 + 27.41 +class ConversionError(Error): 27.42 + pass 27.43 + 27.44 +BOOL_SIZE = 1 27.45 +BOOL_FMT = '>B' 27.46 + 27.47 +BYTE_SIZE = 1 27.48 +BYTE_FMT = '>b' 27.49 +UBYTE_FMT = '>B' 27.50 + 27.51 +SHORT_SIZE = 2 27.52 +SHORT_FMT = '>h' 27.53 +USHORT_FMT = '>H' 27.54 + 27.55 +INT_SIZE = 4 27.56 +INT_FMT = '>l' 27.57 +UINT_FMT = '>L' 27.58 + 27.59 +NONE_CODE = 0 27.60 +NULL_CODE = 1 27.61 +INT_CODE = 2 27.62 +STRING_CODE = 3 27.63 +ATOM_CODE = 4 27.64 +BOOL_CODE = 5 27.65 +LIST_CODE = 10 27.66 + 27.67 +class Packer: 27.68 + 27.69 + def __init__(self, io=None): 27.70 + self.reset(io=io) 27.71 + 27.72 + def reset(self, io=None): 27.73 + if io is None: 27.74 + io = _StringIO() 27.75 + self.io = io 27.76 + 27.77 + def get_buffer(self): 27.78 + return self.io.getvalue() 27.79 + 27.80 + def get_io(self): 27.81 + return self.io 27.82 + 27.83 + def struct_pack(self, fmt, x): 27.84 + try: 27.85 + self.io.write(struct.pack(fmt, x)) 27.86 + except struct.error, msg: 27.87 + raise ConversionError, msg 27.88 + 27.89 + def pack_none(self): 27.90 + pass 27.91 + 27.92 + def pack_bool(self, x): 27.93 + # { '1' | '0' } 27.94 + print 'bool>', x 27.95 + if x: 27.96 + self.io.write('\1') 27.97 + else: 27.98 + self.io.write('\0') 27.99 + 27.100 + def pack_byte(self, x): 27.101 + self.struct_pack(BYTE_FMT, x & 0xff) 27.102 + 27.103 + def pack_char(self, x): 27.104 + print 'char>', x 27.105 + self.io.write(x) 27.106 + 27.107 + def pack_ubyte(self, x): 27.108 + print 'ubyte>', x 27.109 + self.struct_pack(UBYTE_FMT, x & 0xff) 27.110 + 27.111 + def pack_ushort(self, x): 27.112 + print 'ushort>', x 27.113 + self.struct_pack(USHORT_FMT, x & 0xffff) 27.114 + 27.115 + def pack_short(self, x): 27.116 + print 'short>', x 27.117 + self.struct_pack(SHORT_FMT, x & 0xffff) 27.118 + 27.119 + def pack_uint(self, x): 27.120 + print 'uint>', x 27.121 + self.struct_pack(UINT_FMT, x) 27.122 + 27.123 + def pack_int(self, x): 27.124 + print 'int>', x 27.125 + self.struct_pack(INT_FMT, x) 27.126 + 27.127 + def pack_uhyper(self, x): 27.128 + print 'uhyper>', x 27.129 + self.pack_uint(x>>32 & 0xffffffffL) 27.130 + self.pack_uint(x & 0xffffffffL) 27.131 + 27.132 + pack_hyper = pack_uhyper 27.133 + 27.134 + def pack_fstring(self, n, x): 27.135 + print 'fstring>', x 27.136 + self.io.write(x) 27.137 + 27.138 + pack_fopaque = pack_fstring 27.139 + 27.140 + def pack_string(self, x): 27.141 + print 'string>', x 27.142 + n = len(x) 27.143 + self.pack_ushort(n) 27.144 + self.pack_fstring(n, x) 27.145 + 27.146 + pack_opaque = pack_string 27.147 + pack_bytes = pack_string 27.148 + 27.149 + def pack_list(self, x, pack_item): 27.150 + print 'list>', x 27.151 + # { '1' <item> }* '0' 27.152 + for item in x: 27.153 + self.pack_bool(1) 27.154 + pack_item(item) 27.155 + self.pack_bool(0) 27.156 + 27.157 + def pack_farray(self, x, pack_item): 27.158 + # <item>* 27.159 + # Can pass n and check length - but is it worth it? 27.160 + print 'farray>', list 27.161 + for item in x: 27.162 + pack_item(item) 27.163 + 27.164 + def pack_array(self, x, pack_item): 27.165 + # n <item>*n 27.166 + print 'array>', x 27.167 + self.pack_uint(len(x)) 27.168 + self.pack_farray(x, pack_item) 27.169 + 27.170 +class Unpacker: 27.171 + 27.172 + def __init__(self, data): 27.173 + self.reset(data) 27.174 + 27.175 + def reset(self, data): 27.176 + if isinstance(data, types.StringType): 27.177 + data = _StringIO(data) 27.178 + self.io = data 27.179 + 27.180 + def get_bytes(self, n): 27.181 + if n < 0: 27.182 + raise ConversionError('negative byte count') 27.183 + data = self.io.read(n) 27.184 + return data 27.185 + 27.186 + def struct_unpack(self, fmt, n): 27.187 + data = self.get_bytes(n) 27.188 + try: 27.189 + return struct.unpack(fmt, data)[0] 27.190 + except struct.error, msg: 27.191 + raise ConversionError, msg 27.192 + 27.193 + def unpack_none(self): 27.194 + return None 27.195 + 27.196 + def unpack_bool(self): 27.197 + return self.struct_unpack(BOOL_FMT, BOOL_SIZE) 27.198 + 27.199 + def unpack_char(self): 27.200 + return self.get_bytes(1)[0] 27.201 + 27.202 + def unpack_byte(self): 27.203 + return self.struct_unpack(BYTE_FMT, BYTE_SIZE) 27.204 + 27.205 + def unpack_ubyte(self): 27.206 + return self.struct_unpack(UBYTE_FMT, BYTE_SIZE) 27.207 + 27.208 + def unpack_ushort(self): 27.209 + return self.struct_unpack(USHORT_FMT, SHORT_SIZE) 27.210 + 27.211 + def unpack_short(self): 27.212 + return self.struct_unpack(SHORT_FMT, SHORT_SIZE) 27.213 + 27.214 + def unpack_uint(self): 27.215 + x = self.struct_unpack(UINT_FMT, UINT_SIZE) 27.216 + try: 27.217 + return int(x) 27.218 + except OverflowError: 27.219 + return x 27.220 + 27.221 + def unpack_int(self): 27.222 + return self.struct_unpack(INT_FMT, INT_SIZE) 27.223 + 27.224 + def unpack_uhyper(self): 27.225 + hi = self.unpack_uint() 27.226 + lo = self.unpack_uint() 27.227 + return long(hi)<<32 | lo 27.228 + 27.229 + def unpack_hyper(self): 27.230 + x = self.unpack_uhyper() 27.231 + if x >= 0x8000000000000000L: 27.232 + x = x - 0x10000000000000000L 27.233 + return x 27.234 + 27.235 + def unpack_fstring(self, n): 27.236 + return self.get_bytes(n) 27.237 + 27.238 + unpack_fopaque = unpack_fstring 27.239 + 27.240 + def unpack_string(self): 27.241 + n = self.unpack_ushort() 27.242 + return self.unpack_fstring(n) 27.243 + 27.244 + unpack_opaque = unpack_string 27.245 + unpack_bytes = unpack_string 27.246 + 27.247 + def unpack_list(self, unpack_item): 27.248 + list = [] 27.249 + while self.unpack_bool(): 27.250 + list.append(unpack_item()) 27.251 + return list 27.252 + 27.253 + def unpack_farray(self, n, unpack_item): 27.254 + list = [] 27.255 + for i in range(n): 27.256 + list.append(unpack_item()) 27.257 + return list 27.258 + 27.259 + def unpack_array(self, unpack_item): 27.260 + n = self.unpack_ushort() 27.261 + return self.unpack_farray(n, unpack_item) 27.262 + 27.263 +class SxpPacker(Packer): 27.264 + 27.265 + pack_code = Packer.pack_ushort 27.266 + 27.267 + def pack(self, x): 27.268 + if isinstance(x, types.NoneType): 27.269 + self.pack_code(NONE_CODE) 27.270 + self.pack_none() 27.271 + elif isinstance(x, types.IntType): 27.272 + self.pack_code(INT_CODE) 27.273 + self.pack_int(x) 27.274 + elif isinstance(x, types.StringType): 27.275 + self.pack_code(STRING_CODE) 27.276 + self.pack_string(x) 27.277 + elif isinstance(x, types.ListType): 27.278 + self.pack_code(LIST_CODE) 27.279 + self.pack_list(x, self.pack) 27.280 + else: 27.281 + raise Error('invalid type ' + str(type(x))) 27.282 + 27.283 +class SxpUnpacker(Unpacker): 27.284 + 27.285 + unpack_code = Unpacker.unpack_ushort 27.286 + 27.287 + def unpack(self): 27.288 + code = self.unpack_code() 27.289 + if code == NONE_CODE: 27.290 + val = self.unpack_none() 27.291 + elif code == INT_CODE: 27.292 + val = self.unpack_int() 27.293 + elif code == BOOL_CODE: 27.294 + val = self.unpack_bool() 27.295 + elif code == STRING_CODE: 27.296 + val = self.unpack_string() 27.297 + elif code == ATOM_CODE: 27.298 + val = self.unpack_string() 27.299 + elif code == LIST_CODE: 27.300 + val = self.unpack_list(self.unpack) 27.301 + else: 27.302 + raise Error('invalid code ' + str(code)) 27.303 + return val 27.304 + 27.305 +def main(): 27.306 + d = "['vfarm', ['@', ['name', 'vfarm1']], ['memory', 1024], ['image', 'splinux'], ['args', 'root=/dev/nfs ip=dhcp'], [ 1, -1, 1000000]]" 27.307 + print"> len=", len(d), "d=", d 27.308 + obj = ['vfarm', ['@', ['name', 'vfarm1']], 27.309 + ['memory', 1024], 27.310 + ['image', 'splinux'], 27.311 + ['args', 'root=/dev/nfs ip=dhcp'], 27.312 + [ 1, -1, 1000000] ] 27.313 + print "> obj=", obj 27.314 + pack = SxpPacker() 27.315 + pack.pack(obj) 27.316 + data = pack.get_buffer() 27.317 + print "> len=", len(data), "data=", data 27.318 + unpack = SxpUnpacker(data) 27.319 + obj_unpack = unpack.unpack() 27.320 + print "> obj=", obj_unpack 27.321 + #obj = [100,101,102, 999.00234, { 'a': 1, 'b': 2 } ] 27.322 + #pack.reset() 27.323 + #pack.pack_item(obj) 27.324 + #data = pack.get_buffer() 27.325 + #print "> obj=", obj 27.326 + #print "> len=", len(data), "data=", data 27.327 + #unpack.reset(data) 27.328 + #obj_unpack = unpack.unpack_item() 27.329 + #print "> obj=", obj_unpack 27.330 + 27.331 +if __name__ == "__main__": 27.332 + main()
28.1 --- a/tools/python/xen/xend/server/SrvBase.py Tue Jul 06 17:25:40 2004 +0000 28.2 +++ b/tools/python/xen/xend/server/SrvBase.py Tue Jul 06 17:27:27 2004 +0000 28.3 @@ -8,6 +8,7 @@ import types 28.4 import StringIO 28.5 28.6 from twisted.internet import defer 28.7 +defer.Deferred.debug = 1 28.8 from twisted.internet import reactor 28.9 from twisted.web import error 28.10 from twisted.web import resource
29.1 --- a/tools/python/xen/xend/server/SrvDaemon.py Tue Jul 06 17:25:40 2004 +0000 29.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py Tue Jul 06 17:27:27 2004 +0000 29.3 @@ -23,6 +23,7 @@ from twisted.internet import reactor 29.4 from twisted.internet import protocol 29.5 from twisted.internet import abstract 29.6 from twisted.internet import defer 29.7 +defer.Deferred.debug = 1 29.8 29.9 from xen.lowlevel import xu 29.10
30.1 --- a/tools/python/xen/xend/server/SrvDomain.py Tue Jul 06 17:25:40 2004 +0000 30.2 +++ b/tools/python/xen/xend/server/SrvDomain.py Tue Jul 06 17:27:27 2004 +0000 30.3 @@ -27,7 +27,11 @@ class SrvDomain(SrvDir): 30.4 return val 30.5 30.6 def op_shutdown(self, op, req): 30.7 - val = self.xd.domain_shutdown(self.dom.id) 30.8 + #val = self.xd.domain_shutdown(self.dom.id) 30.9 + fn = FormFn(self.xd.domain_shutdown, 30.10 + [['dom', 'int'], 30.11 + ['reason', 'str']]) 30.12 + val = fn(req.args, {'dom': self.dom.id}) 30.13 req.setResponseCode(202) 30.14 req.setHeader("Location", "%s/.." % req.prePathURL()) 30.15 return val
31.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py Tue Jul 06 17:25:40 2004 +0000 31.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Tue Jul 06 17:27:27 2004 +0000 31.3 @@ -1,5 +1,6 @@ 31.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 31.5 31.6 +import traceback 31.7 from StringIO import StringIO 31.8 31.9 from twisted.protocols import http 31.10 @@ -24,6 +25,7 @@ class SrvDomainDir(SrvDir): 31.11 val = None 31.12 try: 31.13 dom = self.xd.domain_get(x) 31.14 + if not dom: raise KeyError('No such domain') 31.15 val = SrvDomain(dom) 31.16 except KeyError, ex: 31.17 print 'SrvDomainDir>', ex 31.18 @@ -38,6 +40,9 @@ class SrvDomainDir(SrvDir): 31.19 return v 31.20 31.21 def op_create(self, op, req): 31.22 + """Create a domain. 31.23 + Expects the domain config in request parameter 'config' in SXP format. 31.24 + """ 31.25 ok = 0 31.26 try: 31.27 configstring = req.args.get('config')[0] 31.28 @@ -48,7 +53,8 @@ class SrvDomainDir(SrvDir): 31.29 config = pin.get_val() 31.30 ok = 1 31.31 except Exception, ex: 31.32 - print 'op_create>', ex 31.33 + print 'op_create> Exception in config', ex 31.34 + traceback.print_exc() 31.35 if not ok: 31.36 req.setResponseCode(http.BAD_REQUEST, "Invalid configuration") 31.37 return "Invalid configuration" 31.38 @@ -57,19 +63,20 @@ class SrvDomainDir(SrvDir): 31.39 "Invalid configuration") 31.40 try: 31.41 deferred = self.xd.domain_create(config) 31.42 - deferred.addCallback(self._cb_op_create, configstring, req) 31.43 + deferred.addCallback(self._op_create_cb, configstring, req) 31.44 + deferred.addErrback(self._op_create_err, req) 31.45 return deferred 31.46 except Exception, ex: 31.47 - raise 31.48 - #return ['err', str(ex) ] 31.49 - #req.setResponseCode(http.BAD_REQUEST, "Error creating domain") 31.50 - #return str(ex) 31.51 + print 'op_create> Exception creating domain:' 31.52 + traceback.print_exc() 31.53 + req.setResponseCode(http.BAD_REQUEST, "Error creating domain") 31.54 + return str(ex) 31.55 #return error.ErrorPage(http.BAD_REQUEST, 31.56 # "Error creating domain", 31.57 # str(ex)) 31.58 31.59 31.60 - def _cb_op_create(self, dominfo, configstring, req): 31.61 + def _op_create_cb(self, dominfo, configstring, req): 31.62 """Callback to handle deferred domain creation. 31.63 """ 31.64 dom = dominfo.id 31.65 @@ -89,7 +96,16 @@ class SrvDomainDir(SrvDir): 31.66 out.close() 31.67 return val 31.68 31.69 + def _op_create_err(self, err, req): 31.70 + """Callback to handle errors in deferred domain creation. 31.71 + """ 31.72 + print 'op_create> Deferred Exception creating domain:', err 31.73 + req.setResponseCode(http.BAD_REQUEST, "Error creating domain") 31.74 + return str(err) 31.75 + 31.76 def op_restore(self, op, req): 31.77 + """Restore a domain from file. 31.78 + """ 31.79 fn = FormFn(self.xd.domain_restore, 31.80 [['file', 'str']]) 31.81 val = fn(req.args) 31.82 @@ -131,6 +147,8 @@ class SrvDomainDir(SrvDir): 31.83 req.write('</ul>') 31.84 31.85 def form(self, req): 31.86 + """Generate the form(s) for domain dir operations. 31.87 + """ 31.88 req.write('<form method="post" action="%s" enctype="multipart/form-data">' 31.89 % req.prePathURL()) 31.90 req.write('<button type="submit" name="op" value="create">Create Domain</button>')
32.1 --- a/tools/python/xen/xend/server/blkif.py Tue Jul 06 17:25:40 2004 +0000 32.2 +++ b/tools/python/xen/xend/server/blkif.py Tue Jul 06 17:27:27 2004 +0000 32.3 @@ -1,4 +1,7 @@ 32.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 32.5 + 32.6 from twisted.internet import defer 32.7 +defer.Deferred.debug = 1 32.8 32.9 from xen.xend import sxp 32.10 from xen.xend import PrettyPrint 32.11 @@ -18,53 +21,78 @@ class BlkifControllerFactory(controller. 32.12 self.majorTypes = [ CMSG_BLKIF_BE ] 32.13 32.14 self.subTypes = { 32.15 - CMSG_BLKIF_BE_CREATE : self.recv_be_create, 32.16 - CMSG_BLKIF_BE_CONNECT : self.recv_be_connect, 32.17 - CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create, 32.18 - CMSG_BLKIF_BE_VBD_GROW : self.recv_be_vbd_grow, 32.19 CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed, 32.20 } 32.21 self.attached = 1 32.22 self.registerChannel() 32.23 32.24 def createInstance(self, dom, recreate=0): 32.25 - d = self.addDeferred() 32.26 + """Create a block device controller for a domain. 32.27 + 32.28 + dom domain 32.29 + recreate if true it's a recreate (after xend restart) 32.30 + """ 32.31 + d = defer.Deferred() 32.32 blkif = self.getInstanceByDom(dom) 32.33 if blkif: 32.34 - self.callDeferred(blkif) 32.35 + d.callback(blkif) 32.36 else: 32.37 blkif = BlkifController(self, dom) 32.38 self.addInstance(blkif) 32.39 if recreate: 32.40 - self.callDeferred(blkif) 32.41 + d.callback(blkif) 32.42 else: 32.43 - blkif.send_be_create() 32.44 + d1 = defer.Deferred() 32.45 + d1.addCallback(self.respond_be_create, d) 32.46 + d1.addErrback(d.errback) 32.47 + blkif.send_be_create(response=d1) 32.48 return d 32.49 32.50 def getDomainDevices(self, dom): 32.51 + """Get the block devices for a domain. 32.52 + 32.53 + dom domain 32.54 + 32.55 + returns devices 32.56 + """ 32.57 blkif = self.getInstanceByDom(dom) 32.58 return (blkif and blkif.getDevices()) or [] 32.59 32.60 def getDomainDevice(self, dom, vdev): 32.61 + """Get a block device from a domain. 32.62 + 32.63 + dom domain 32.64 + vdev device index 32.65 + 32.66 + returns device 32.67 + """ 32.68 blkif = self.getInstanceByDom(dom) 32.69 return (blkif and blkif.getDevice(vdev)) or None 32.70 32.71 def setControlDomain(self, dom, recreate=0): 32.72 + """Set the back-end block device controller domain. 32.73 + 32.74 + dom domain 32.75 + recreate if true it's a recreate (after xend restart) 32.76 + """ 32.77 if self.dom == dom: return 32.78 self.deregisterChannel() 32.79 if not recreate: 32.80 self.attached = 0 32.81 self.dom = dom 32.82 self.registerChannel() 32.83 - # 32.84 - #if xend.blkif.be_port: 32.85 - # xend.blkif.recovery = True 32.86 - #xend.blkif.be_port = xend.main.port_from_dom(dom) 32.87 32.88 def getControlDomain(self): 32.89 + """Get the back-end block device controller domain. 32.90 + """ 32.91 return self.dom 32.92 32.93 def reattachDevice(self, dom, vdev): 32.94 + """Reattach a device (on changing control domain). 32.95 + 32.96 + dom domain 32.97 + vdev device index 32.98 + """ 32.99 blkif = self.getInstanceByDom(dom) 32.100 if blkif: 32.101 blkif.reattachDevice(vdev) 32.102 @@ -83,17 +111,20 @@ class BlkifControllerFactory(controller. 32.103 return attached 32.104 32.105 def reattached(self): 32.106 + """Notify all block interface we have been reattached 32.107 + (after changing control domain). 32.108 + """ 32.109 for blkif in self.getInstances(): 32.110 blkif.reattached() 32.111 32.112 - def recv_be_create(self, msg, req): 32.113 - #print 'recv_be_create>' 32.114 + def respond_be_create(self, msg, d): 32.115 + print 'respond_be_create>' 32.116 val = unpackMsg('blkif_be_create_t', msg) 32.117 blkif = self.getInstanceByDom(val['domid']) 32.118 - self.callDeferred(blkif) 32.119 + d.callback(blkif) 32.120 32.121 - def recv_be_connect(self, msg, req): 32.122 - #print 'recv_be_create>' 32.123 + def respond_be_connect(self, msg): 32.124 + print 'respond_be_connect>', self 32.125 val = unpackMsg('blkif_be_connect_t', msg) 32.126 blkif = self.getInstanceByDom(val['domid']) 32.127 if blkif: 32.128 @@ -101,25 +132,30 @@ class BlkifControllerFactory(controller. 32.129 else: 32.130 pass 32.131 32.132 - def recv_be_vbd_create(self, msg, req): 32.133 - #print 'recv_be_vbd_create>' 32.134 + def respond_be_vbd_create(self, msg, d): 32.135 + print 'recv_be_vbd_create>', self 32.136 val = unpackMsg('blkif_be_vbd_create_t', msg) 32.137 blkif = self.getInstanceByDom(val['domid']) 32.138 if blkif: 32.139 - blkif.send_be_vbd_grow(val['vdevice']) 32.140 + d1 = defer.Deferred() 32.141 + d1.addCallback(self.respond_be_vbd_grow, d) 32.142 + if d: d1.addErrback(d.errback) 32.143 + blkif.send_be_vbd_grow(val['vdevice'], response=d1) 32.144 else: 32.145 pass 32.146 32.147 - def recv_be_vbd_grow(self, msg, req): 32.148 - #print 'recv_be_vbd_grow>' 32.149 + def respond_be_vbd_grow(self, msg, d): 32.150 + print 'recv_be_vbd_grow>', self 32.151 val = unpackMsg('blkif_be_vbd_grow_t', msg) 32.152 # Check status? 32.153 if self.attached: 32.154 - self.callDeferred(0) 32.155 + if d: 32.156 + d.callback(0) 32.157 else: 32.158 self.reattachDevice(val['domid'], val['vdevice']) 32.159 32.160 def recv_be_driver_status_changed(self, msg, req): 32.161 + print 'recv_be_driver_status_changed>', self, req 32.162 val = unpackMsg('blkif_be_driver_status_changed_t', msg) 32.163 status = val['status'] 32.164 if status == BLKIF_DRIVER_STATUS_UP and not self.attached: 32.165 @@ -147,7 +183,6 @@ class BlkDev(controller.Dev): 32.166 return val 32.167 32.168 def destroy(self): 32.169 - print 'BlkDev>destroy>', self.vdev 32.170 PrettyPrint.prettyprint(self.sxpr()) 32.171 self.controller.send_be_vbd_destroy(self.vdev) 32.172 32.173 @@ -157,7 +192,6 @@ class BlkifController(controller.Control 32.174 """ 32.175 32.176 def __init__(self, factory, dom): 32.177 - #print 'BlkifController> dom=', dom 32.178 controller.Controller.__init__(self, factory, dom) 32.179 self.devices = {} 32.180 32.181 @@ -172,7 +206,6 @@ class BlkifController(controller.Control 32.182 self.attached = 1 32.183 self.evtchn = None 32.184 self.registerChannel() 32.185 - #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx 32.186 32.187 def sxpr(self): 32.188 val = ['blkif', ['dom', self.dom]] 32.189 @@ -182,11 +215,6 @@ class BlkifController(controller.Control 32.190 self.evtchn['port2']]) 32.191 return val 32.192 32.193 - def lostChannel(self): 32.194 - print 'BlkifController>lostChannel>', 'dom=', self.dom 32.195 - #self.destroyDevices() 32.196 - controller.Controller.lostChannel(self) 32.197 - 32.198 def getDevices(self): 32.199 return self.devices.values() 32.200 32.201 @@ -201,26 +229,32 @@ class BlkifController(controller.Control 32.202 32.203 def attachDevice(self, vdev, mode, segment, recreate=0): 32.204 """Attach a device to the specified interface. 32.205 + 32.206 + vdev device index 32.207 + mode read/write mode 32.208 + segment segment 32.209 + recreate if true it's being recreated (after xend restart) 32.210 + 32.211 + returns deferred 32.212 """ 32.213 - #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment 32.214 dev = self.addDevice(vdev, mode, segment) 32.215 if not dev: return -1 32.216 + d = defer.Deferred() 32.217 if recreate: 32.218 - d = defer.Deferred() 32.219 d.callback(self) 32.220 else: 32.221 - self.send_be_vbd_create(vdev) 32.222 - d = self.factory.addDeferred() 32.223 + d1 = defer.Deferred() 32.224 + d1.addCallback(self.factory.respond_be_vbd_create, d) 32.225 + d1.addErrback(d.errback) 32.226 + self.send_be_vbd_create(vdev, response=d1) 32.227 return d 32.228 32.229 def destroy(self): 32.230 - print 'BlkifController>destroy> dom=', self.dom 32.231 def cb_destroy(val): 32.232 self.send_be_destroy() 32.233 - d = self.factory.addDeferred() 32.234 + d = defer.Deferred() 32.235 d.addCallback(cb_destroy) 32.236 - self.send_be_disconnect() 32.237 - #self.destroyDevices() 32.238 + self.send_be_disconnect(response=d) 32.239 32.240 def destroyDevices(self): 32.241 for dev in self.getDevices(): 32.242 @@ -232,7 +266,9 @@ class BlkifController(controller.Control 32.243 self.attached = 0 32.244 for dev in self.devices.values(): 32.245 dev.attached = 0 32.246 - self.send_be_vbd_create(vdev) 32.247 + d1 = defer.Deferred() 32.248 + d1.addCallback(self.factory.respond_be_vbd_create, None) 32.249 + self.send_be_vbd_create(vdev, response=d1) 32.250 32.251 def reattachDevice(self, vdev): 32.252 """Reattach a device, when the back-end control domain has changed. 32.253 @@ -273,51 +309,47 @@ class BlkifController(controller.Control 32.254 'blkif_handle' : val['handle'], 32.255 'evtchn' : self.evtchn['port1'], 32.256 'shmem_frame' : val['shmem_frame'] }) 32.257 - self.factory.writeRequest(msg) 32.258 - pass 32.259 + d = defer.Deferred() 32.260 + d.addCallback(self.factory.respond_be_connect) 32.261 + self.factory.writeRequest(msg, response=d) 32.262 32.263 - #def recv_fe_interface_status_changed(self, msg, req): 32.264 - # (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg) 32.265 - # print 'recv_fe_interface_status_changed>', hnd, status, chan 32.266 - # pass 32.267 - 32.268 - def send_fe_interface_status_changed(self): 32.269 + def send_fe_interface_status_changed(self, response=None): 32.270 msg = packMsg('blkif_fe_interface_status_changed_t', 32.271 { 'handle' : 0, 32.272 'status' : BLKIF_INTERFACE_STATUS_CONNECTED, 32.273 'evtchn' : self.evtchn['port2'] }) 32.274 - self.writeRequest(msg) 32.275 + self.writeRequest(msg, response=response) 32.276 32.277 - def send_be_create(self): 32.278 + def send_be_create(self, response=None): 32.279 msg = packMsg('blkif_be_create_t', 32.280 { 'domid' : self.dom, 32.281 'blkif_handle' : 0 }) 32.282 - self.factory.writeRequest(msg) 32.283 + self.factory.writeRequest(msg, response=response) 32.284 32.285 - def send_be_disconnect(self): 32.286 + def send_be_disconnect(self, response=None): 32.287 print '>BlkifController>send_be_disconnect>', 'dom=', self.dom 32.288 msg = packMsg('blkif_be_disconnect_t', 32.289 { 'domid' : self.dom, 32.290 'blkif_handle' : 0 }) 32.291 - self.factory.writeRequest(msg) 32.292 + self.factory.writeRequest(msg, response=response) 32.293 32.294 - def send_be_destroy(self): 32.295 + def send_be_destroy(self, response=None): 32.296 print '>BlkifController>send_be_destroy>', 'dom=', self.dom 32.297 msg = packMsg('blkif_be_destroy_t', 32.298 { 'domid' : self.dom, 32.299 'blkif_handle' : 0 }) 32.300 - self.factory.writeRequest(msg) 32.301 + self.factory.writeRequest(msg, response=response) 32.302 32.303 - def send_be_vbd_create(self, vdev): 32.304 + def send_be_vbd_create(self, vdev, response=None): 32.305 dev = self.devices[vdev] 32.306 msg = packMsg('blkif_be_vbd_create_t', 32.307 { 'domid' : self.dom, 32.308 'blkif_handle' : 0, 32.309 'vdevice' : dev.vdev, 32.310 'readonly' : dev.readonly() }) 32.311 - self.factory.writeRequest(msg) 32.312 + self.factory.writeRequest(msg, response=response) 32.313 32.314 - def send_be_vbd_grow(self, vdev): 32.315 + def send_be_vbd_grow(self, vdev, response=None): 32.316 dev = self.devices[vdev] 32.317 msg = packMsg('blkif_be_vbd_grow_t', 32.318 { 'domid' : self.dom, 32.319 @@ -326,9 +358,9 @@ class BlkifController(controller.Control 32.320 'extent.device' : dev.device, 32.321 'extent.sector_start' : dev.start_sector, 32.322 'extent.sector_length' : dev.nr_sectors }) 32.323 - self.factory.writeRequest(msg) 32.324 + self.factory.writeRequest(msg, response=response) 32.325 32.326 - def send_be_vbd_destroy(self, vdev): 32.327 + def send_be_vbd_destroy(self, vdev, response=None): 32.328 print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev 32.329 PrettyPrint.prettyprint(self.sxpr()) 32.330 dev = self.devices[vdev] 32.331 @@ -337,5 +369,5 @@ class BlkifController(controller.Control 32.332 'blkif_handle' : 0, 32.333 'vdevice' : dev.vdev }) 32.334 del self.devices[vdev] 32.335 - self.factory.writeRequest(msg) 32.336 + self.factory.writeRequest(msg, response=response) 32.337
33.1 --- a/tools/python/xen/xend/server/channel.py Tue Jul 06 17:25:40 2004 +0000 33.2 +++ b/tools/python/xen/xend/server/channel.py Tue Jul 06 17:27:27 2004 +0000 33.3 @@ -1,3 +1,5 @@ 33.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 33.5 + 33.6 import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() 33.7 from xen.lowlevel import xu 33.8 from messages import msgTypeName 33.9 @@ -24,14 +26,11 @@ class ChannelFactory: 33.10 self.notifier = xu.notifier() 33.11 33.12 def addChannel(self, channel): 33.13 - """Add a channel. 33.14 + """Add a channel. Registers with the notifier. 33.15 """ 33.16 idx = channel.idx 33.17 self.channels[idx] = channel 33.18 self.notifier.bind(idx) 33.19 - # Try to wake it up 33.20 - #self.notifier.unmask(idx) 33.21 - #channel.notify() 33.22 33.23 def getChannel(self, idx): 33.24 """Get the channel with the given index (if any). 33.25 @@ -40,6 +39,7 @@ class ChannelFactory: 33.26 33.27 def delChannel(self, idx): 33.28 """Remove the channel with the given index (if any). 33.29 + Deregisters with the notifier. 33.30 """ 33.31 if idx in self.channels: 33.32 del self.channels[idx] 33.33 @@ -174,9 +174,9 @@ class VirqChannel(BaseChannel): 33.34 """Close the channel. Calls lostChannel(self) on all its clients and 33.35 channelClosed() on the factory. 33.36 """ 33.37 - for c in self.clients: 33.38 + for c in self.clients[:]: 33.39 c.lostChannel(self) 33.40 - del self.clients 33.41 + self.clients = [] 33.42 BaseChannel.close(self) 33.43 33.44 def registerClient(self, client): 33.45 @@ -238,7 +238,7 @@ class Channel(BaseChannel): 33.46 """ 33.47 if self.closed: return 33.48 self.closed = 1 33.49 - for d in self.devs: 33.50 + for d in self.devs[:]: 33.51 d.lostChannel() 33.52 self.factory.channelClosed(self) 33.53 self.devs = [] 33.54 @@ -288,6 +288,8 @@ class Channel(BaseChannel): 33.55 self.getRemotePort())) 33.56 33.57 def handleNotification(self): 33.58 + """Process outstanding messages in repsonse to notification on the port. 33.59 + """ 33.60 if self.closed: 33.61 print 'handleNotification> Notification on closed channel', self 33.62 return 33.63 @@ -299,6 +301,8 @@ class Channel(BaseChannel): 33.64 self.notify() 33.65 33.66 def notify(self): 33.67 + """Notify the other end of the port that messages have been processed. 33.68 + """ 33.69 if self.closed: return 33.70 self.port.notify() 33.71
34.1 --- a/tools/python/xen/xend/server/console.py Tue Jul 06 17:25:40 2004 +0000 34.2 +++ b/tools/python/xen/xend/server/console.py Tue Jul 06 17:27:27 2004 +0000 34.3 @@ -1,3 +1,4 @@ 34.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 34.5 34.6 from twisted.internet import reactor 34.7 from twisted.internet import protocol 34.8 @@ -12,11 +13,6 @@ import controller 34.9 from messages import * 34.10 from params import * 34.11 34.12 -"""Telnet binary option.""" 34.13 -TRANSMIT_BINARY = '0' 34.14 -WILL = chr(251) 34.15 -IAC = chr(255) 34.16 - 34.17 class ConsoleProtocol(protocol.Protocol): 34.18 """Asynchronous handler for a console TCP socket. 34.19 """ 34.20 @@ -36,19 +32,12 @@ class ConsoleProtocol(protocol.Protocol) 34.21 self.loseConnection() 34.22 return 34.23 else: 34.24 - # KAF: A nice quiet successful connect. Don't bother with telnet 34.25 - # control sequence -- telnet is not the appropriate protocol here. 34.26 + # KAF: A nice quiet successful connect. 34.27 #self.transport.write("Connected to console %d on domain %d\n" 34.28 # % (self.idx, self.controller.dom)) 34.29 - #self.setTelnetTransmitBinary() 34.30 eserver.inject('xend.console.connect', 34.31 [self.idx, self.addr[0], self.addr[1]]) 34.32 34.33 - def setTelnetTransmitBinary(self): 34.34 - """Send the sequence to set the telnet TRANSMIT-BINARY option. 34.35 - """ 34.36 - self.write(IAC + WILL + TRANSMIT_BINARY) 34.37 - 34.38 def dataReceived(self, data): 34.39 if self.controller.handleInput(self, data): 34.40 self.loseConnection() 34.41 @@ -104,11 +93,15 @@ class ConsoleController(controller.Contr 34.42 output and the connected TCP sockets to post console input. 34.43 """ 34.44 34.45 + STATUS_NEW = 'new' 34.46 + STATUS_CLOSED = 'closed' 34.47 + STATUS_CONNECTED = 'connected' 34.48 + STATUS_LISTENING = 'listening' 34.49 + 34.50 def __init__(self, factory, dom, console_port): 34.51 - #print 'ConsoleController> dom=', dom, type(dom) 34.52 controller.Controller.__init__(self, factory, dom) 34.53 self.majorTypes = [ CMSG_CONSOLE ] 34.54 - self.status = "new" 34.55 + self.status = self.STATUS_NEW 34.56 self.addr = None 34.57 self.conn = None 34.58 self.rbuf = xu.buffer() 34.59 @@ -118,7 +111,6 @@ class ConsoleController(controller.Contr 34.60 self.registerChannel() 34.61 self.listener = None 34.62 self.listen() 34.63 - #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx 34.64 34.65 def sxpr(self): 34.66 val =['console', 34.67 @@ -136,29 +128,31 @@ class ConsoleController(controller.Contr 34.68 return not (self.closed() or self.rbuf.empty()) 34.69 34.70 def closed(self): 34.71 - return self.status == 'closed' 34.72 + return self.status == self.STATUS_CLOSED 34.73 34.74 def connected(self): 34.75 - return self.status == 'connected' 34.76 + return self.status == self.STATUS_CONNECTED 34.77 34.78 def close(self): 34.79 - try: 34.80 - #print 'ConsoleController> close dom=', self.dom 34.81 - self.status = "closed" 34.82 - if self.conn: 34.83 - self.conn.loseConnection() 34.84 - self.listener.stopListening() 34.85 - self.deregisterChannel() 34.86 - self.lostChannel() 34.87 - except Exception, ex: 34.88 - print 'ConsoleController>close>', ex 34.89 - raise 34.90 + """Close the console controller. 34.91 + """ 34.92 + self.lostChannel() 34.93 + 34.94 + def lostChannel(self): 34.95 + """The channel to the domain has been lost. 34.96 + Cleanup: disconnect TCP connections and listeners, notify the controller. 34.97 + """ 34.98 + self.status = self.STATUS_CLOSED 34.99 + if self.conn: 34.100 + self.conn.loseConnection() 34.101 + self.listener.stopListening() 34.102 + controller.Controller.lostChannel(self) 34.103 34.104 def listen(self): 34.105 """Listen for TCP connections to the console port.. 34.106 """ 34.107 if self.closed(): return 34.108 - self.status = "listening" 34.109 + self.status = self.STATUS_LISTENING 34.110 if self.listener: 34.111 #self.listener.startListening() 34.112 pass 34.113 @@ -167,15 +161,25 @@ class ConsoleController(controller.Contr 34.114 self.listener = reactor.listenTCP(self.console_port, f) 34.115 34.116 def connect(self, addr, conn): 34.117 + """Connect a TCP connection to the console. 34.118 + Fails if closed or already connected. 34.119 + 34.120 + addr peer address 34.121 + conn connection 34.122 + 34.123 + returns 0 if ok, negative otherwise 34.124 + """ 34.125 if self.closed(): return -1 34.126 if self.connected(): return -1 34.127 self.addr = addr 34.128 self.conn = conn 34.129 - self.status = "connected" 34.130 + self.status = self.STATUS_CONNECTED 34.131 self.handleOutput() 34.132 return 0 34.133 34.134 def disconnect(self): 34.135 + """Disconnect the TCP connection to the console. 34.136 + """ 34.137 if self.conn: 34.138 self.conn.loseConnection() 34.139 self.addr = None 34.140 @@ -183,15 +187,29 @@ class ConsoleController(controller.Contr 34.141 self.listen() 34.142 34.143 def requestReceived(self, msg, type, subtype): 34.144 - #print '***Console', self.dom, msg.get_payload() 34.145 + """Receive console data from the console channel. 34.146 + 34.147 + msg console message 34.148 + type major message type 34.149 + subtype minor message typ 34.150 + """ 34.151 self.rbuf.write(msg.get_payload()) 34.152 self.handleOutput() 34.153 34.154 def responseReceived(self, msg, type, subtype): 34.155 + """Handle a response to a request written to the console channel. 34.156 + Just ignore it because the return values are not interesting. 34.157 + 34.158 + msg console message 34.159 + type major message type 34.160 + subtype minor message typ 34.161 + """ 34.162 pass 34.163 34.164 def produceRequests(self): 34.165 - # Send as much pending console data as there is room for. 34.166 + """Write pending console data to the console channel. 34.167 + Writes as much to the channel as it can. 34.168 + """ 34.169 work = 0 34.170 while not self.wbuf.empty() and self.channel.writeReady(): 34.171 msg = xu.message(CMSG_CONSOLE, 0, 0) 34.172 @@ -201,7 +219,12 @@ class ConsoleController(controller.Contr 34.173 34.174 def handleInput(self, conn, data): 34.175 """Handle some external input aimed at the console. 34.176 - Called from a TCP connection (conn). 34.177 + Called from a TCP connection (conn). Ignores the input 34.178 + if the calling connection (conn) is not the one connected 34.179 + to the console (self.conn). 34.180 + 34.181 + conn connection 34.182 + data input data 34.183 """ 34.184 if self.closed(): return -1 34.185 if conn != self.conn: return 0 34.186 @@ -215,18 +238,14 @@ class ConsoleController(controller.Contr 34.187 Sends it to the connected console (if any). 34.188 """ 34.189 if self.closed(): 34.190 - #print 'Console>handleOutput> closed' 34.191 return -1 34.192 if not self.conn: 34.193 - #print 'Console>handleOutput> not connected' 34.194 return 0 34.195 while not self.rbuf.empty(): 34.196 try: 34.197 - #print 'Console>handleOutput> writing...' 34.198 bytes = self.conn.write(self.rbuf.peek()) 34.199 if bytes > 0: 34.200 self.rbuf.discard(bytes) 34.201 except socket.error, error: 34.202 pass 34.203 - #print 'Console>handleOutput<' 34.204 return 0
35.1 --- a/tools/python/xen/xend/server/controller.py Tue Jul 06 17:25:40 2004 +0000 35.2 +++ b/tools/python/xen/xend/server/controller.py Tue Jul 06 17:27:27 2004 +0000 35.3 @@ -1,10 +1,50 @@ 35.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 35.5 + 35.6 from twisted.internet import defer 35.7 +defer.Deferred.debug = 1 35.8 35.9 import channel 35.10 from messages import msgTypeName 35.11 35.12 +DEBUG=0 35.13 + 35.14 +class OutOfOrderError(RuntimeError): 35.15 + """Error reported when a response arrives out of order. 35.16 + """ 35.17 + pass 35.18 + 35.19 +class Responder: 35.20 + """Handler for a response to a message. 35.21 + """ 35.22 + 35.23 + def __init__(self, mid, deferred): 35.24 + """Create a responder. 35.25 + 35.26 + mid message id of response to handle 35.27 + deferred deferred object holding the callbacks 35.28 + """ 35.29 + self.mid = mid 35.30 + self.deferred = deferred 35.31 + 35.32 + def responseReceived(self, msg): 35.33 + if self.deferred.called: return 35.34 + self.deferred.callback(msg) 35.35 + 35.36 + def error(self, err): 35.37 + if self.deferred.called: return 35.38 + self.deferred.errback(err) 35.39 + 35.40 class CtrlMsgRcvr: 35.41 """Abstract class for things that deal with a control interface to a domain. 35.42 + 35.43 + Instance variables: 35.44 + 35.45 + dom : the domain we are a control interface for 35.46 + majorTypes: list of major message types we are interested in 35.47 + subTypes : mapping of message subtypes to methods 35.48 + 35.49 + channel : channel to the domain 35.50 + idx : channel index 35.51 """ 35.52 35.53 35.54 @@ -15,50 +55,140 @@ class CtrlMsgRcvr: 35.55 self.dom = None 35.56 self.channel = None 35.57 self.idx = None 35.58 + self.responders = [] 35.59 + # Timeout (in seconds) for deferreds. 35.60 + self.timeout = 10 35.61 + 35.62 + def setTimeout(self, timeout): 35.63 + self.timeout = timeout 35.64 35.65 def requestReceived(self, msg, type, subtype): 35.66 + """Dispatch a request to handlers. 35.67 + 35.68 + msg message 35.69 + type major message type 35.70 + subtype minor message type 35.71 + """ 35.72 + msgid = msg.get_header()['id'] 35.73 + if DEBUG: 35.74 + print 'requestReceived>', self, msgid, msgTypeName(type, subtype) 35.75 method = self.subTypes.get(subtype) 35.76 if method: 35.77 method(msg, 1) 35.78 - else: 35.79 + elif DEBUG: 35.80 print ('requestReceived> No handler: Message type %s %d:%d' 35.81 % (msgTypeName(type, subtype), type, subtype)), self 35.82 35.83 def responseReceived(self, msg, type, subtype): 35.84 + """Dispatch a response to handlers. 35.85 + 35.86 + msg message 35.87 + type major message type 35.88 + subtype minor message type 35.89 + """ 35.90 + msgid = msg.get_header()['id'] 35.91 + if DEBUG: 35.92 + print 'responseReceived>', self, msgid, msgTypeName(type, subtype) 35.93 + if self.callResponders(msg): 35.94 + return 35.95 method = self.subTypes.get(subtype) 35.96 if method: 35.97 method(msg, 0) 35.98 - else: 35.99 + elif DEBUG: 35.100 print ('responseReceived> No handler: Message type %s %d:%d' 35.101 % (msgTypeName(type, subtype), type, subtype)), self 35.102 35.103 + def addResponder(self, mid, deferred): 35.104 + """Add a responder for a message id. 35.105 + The deferred is called with callback(msg) when a response 35.106 + with the given message id arrives. Responses are expected 35.107 + to arrive in order of message id. When a response arrives, 35.108 + waiting responders for messages with lower id have errback 35.109 + called with an OutOfOrder error. 35.110 + 35.111 + mid message id of response expected 35.112 + deferred a Deferred to handle the response 35.113 + 35.114 + returns Responder 35.115 + """ 35.116 + if self.timeout > 0: 35.117 + deferred.setTimeout(self.timeout) 35.118 + resp = Responder(mid, deferred) 35.119 + self.responders.append(resp) 35.120 + return resp 35.121 + 35.122 + def callResponders(self, msg): 35.123 + """Call any waiting responders for a response message. 35.124 + 35.125 + msg response message 35.126 + 35.127 + returns 1 if there was a responder for the message, 0 otherwise 35.128 + """ 35.129 + hdr = msg.get_header() 35.130 + mid = hdr['id'] 35.131 + handled = 0 35.132 + while self.responders: 35.133 + resp = self.responders[0] 35.134 + if resp.mid > mid: 35.135 + break 35.136 + self.responders.pop() 35.137 + if resp.mid < mid: 35.138 + print 'handleResponse> Out of order:', resp.mid, mid 35.139 + resp.error(OutOfOrderError()) 35.140 + else: 35.141 + handled = 1 35.142 + resp.responseReceived(msg) 35.143 + break 35.144 + return handled 35.145 + 35.146 def lostChannel(self): 35.147 + """Called when the channel to the domain is lost. 35.148 + """ 35.149 pass 35.150 35.151 def registerChannel(self): 35.152 - #print 'CtrlMsgRcvr>registerChannel>', self 35.153 + """Register interest in our major message types with the 35.154 + channel to our domain. 35.155 + """ 35.156 self.channel = self.channelFactory.domChannel(self.dom) 35.157 self.idx = self.channel.getIndex() 35.158 if self.majorTypes: 35.159 self.channel.registerDevice(self.majorTypes, self) 35.160 35.161 def deregisterChannel(self): 35.162 - #print 'CtrlMsgRcvr>deregisterChannel>', self 35.163 + """Deregister interest in our major message types with the 35.164 + channel to our domain. 35.165 + """ 35.166 if self.channel: 35.167 self.channel.deregisterDevice(self) 35.168 del self.channel 35.169 35.170 def produceRequests(self): 35.171 + """Produce any queued requests. 35.172 + 35.173 + return number produced 35.174 + """ 35.175 return 0 35.176 35.177 - def writeRequest(self, msg): 35.178 + def writeRequest(self, msg, response=None): 35.179 + """Write a request to the channel. 35.180 + 35.181 + msg message 35.182 + response Deferred to handle the response (optional) 35.183 + """ 35.184 if self.channel: 35.185 + if DEBUG: print 'CtrlMsgRcvr>writeRequest>', self, msg 35.186 + if response: 35.187 + self.addResponder(msg.get_header()['id'], response) 35.188 self.channel.writeRequest(msg) 35.189 else: 35.190 print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self 35.191 35.192 def writeResponse(self, msg): 35.193 + """Write a response to the channel. 35.194 + """ 35.195 if self.channel: 35.196 + if DEBUG: print 'CtrlMsgRcvr>writeResponse>', self, msg 35.197 self.channel.writeResponse(msg) 35.198 else: 35.199 print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self 35.200 @@ -66,6 +196,12 @@ class CtrlMsgRcvr: 35.201 class ControllerFactory(CtrlMsgRcvr): 35.202 """Abstract class for factories creating controllers. 35.203 Maintains a table of instances. 35.204 + 35.205 + Instance variables: 35.206 + 35.207 + instances : mapping of index to controller instance 35.208 + dlist : list of deferreds 35.209 + dom : domain 35.210 """ 35.211 35.212 def __init__(self): 35.213 @@ -73,55 +209,46 @@ class ControllerFactory(CtrlMsgRcvr): 35.214 self.instances = {} 35.215 self.dlist = [] 35.216 self.dom = 0 35.217 - # Timeout (in seconds) for deferreds. 35.218 - self.timeout = 10 35.219 35.220 def addInstance(self, instance): 35.221 + """Add a controller instance (under its index). 35.222 + """ 35.223 self.instances[instance.idx] = instance 35.224 35.225 def getInstance(self, idx): 35.226 + """Get a controller instance from its index. 35.227 + """ 35.228 return self.instances.get(idx) 35.229 35.230 def getInstances(self): 35.231 + """Get a list of all controller instances. 35.232 + """ 35.233 return self.instances.values() 35.234 35.235 def getInstanceByDom(self, dom): 35.236 + """Get the controller instance for the given domain. 35.237 + """ 35.238 for inst in self.instances.values(): 35.239 if inst.dom == dom: 35.240 return inst 35.241 return None 35.242 35.243 def delInstance(self, instance): 35.244 - #print 'ControllerFactory>delInstance>', instance.idx 35.245 + """Delete an instance from the table. 35.246 + """ 35.247 if instance.idx in self.instances: 35.248 - #print 'ControllerFactory>delInstance> remove', instance.idx 35.249 del self.instances[instance.idx] 35.250 35.251 def createInstance(self, dom, recreate=0): 35.252 + """Create an instance. Define in a subclass. 35.253 + """ 35.254 raise NotImplementedError() 35.255 35.256 def instanceClosed(self, instance): 35.257 - #print 'ControllerFactory>instanceClosed>', instance.idx, instance 35.258 + """Callback called when an instance is closed (usually by the instance). 35.259 + """ 35.260 self.delInstance(instance) 35.261 35.262 - def addDeferred(self): 35.263 - d = defer.Deferred() 35.264 - if self.timeout > 0: 35.265 - # The deferred will error if not called before timeout. 35.266 - d.setTimeout(self.timeout) 35.267 - self.dlist.append(d) 35.268 - return d 35.269 - 35.270 - def callDeferred(self, *args): 35.271 - if self.dlist: 35.272 - d = self.dlist.pop(0) 35.273 - d.callback(*args) 35.274 - 35.275 - def errDeferred(self, *args): 35.276 - if self.dlist: 35.277 - d = self.dlist.pop(0) 35.278 - d.errback(*args) 35.279 - 35.280 class Controller(CtrlMsgRcvr): 35.281 """Abstract class for a device controller attached to a domain. 35.282 """ 35.283 @@ -134,15 +261,20 @@ class Controller(CtrlMsgRcvr): 35.284 self.idx = None 35.285 35.286 def close(self): 35.287 - self.deregisterChannel() 35.288 + """Close the controller. 35.289 + """ 35.290 self.lostChannel() 35.291 35.292 def lostChannel(self): 35.293 - #print 'Controller>lostChannel>', self, self.factory 35.294 + """The controller channel has been lost. 35.295 + """ 35.296 + self.deregisterChannel() 35.297 self.factory.instanceClosed(self) 35.298 35.299 class Dev: 35.300 - 35.301 + """Abstract class for a device attached to a device controller. 35.302 + """ 35.303 + 35.304 def __init__(self, controller): 35.305 self.controller = controller 35.306 self.props = {} 35.307 @@ -160,9 +292,6 @@ class Dev: 35.308 if k in self.props: 35.309 del self.props[k] 35.310 35.311 - #def __repr__(self): 35.312 - # return str(self.sxpr()) 35.313 - 35.314 def sxpr(self): 35.315 raise NotImplementedError() 35.316
36.1 --- a/tools/python/xen/xend/server/cstruct.py Tue Jul 06 17:25:40 2004 +0000 36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 36.3 @@ -1,269 +0,0 @@ 36.4 -import struct 36.5 - 36.6 -class Struct: 36.7 - 36.8 - maxDepth = 10 36.9 - 36.10 - base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ] 36.11 - 36.12 - sizes = {'B': 1, 36.13 - 'H': 2, 36.14 - 'I': 4, 36.15 - 'L': 4, 36.16 - 'Q': 8, 36.17 - 'c': 1, 36.18 - 'h': 2, 36.19 - 'i': 4, 36.20 - 'l': 4, 36.21 - 'q': 8, 36.22 - 'x': 1, 36.23 - } 36.24 - 36.25 - formats = { 36.26 - 'int8' : 'B', 36.27 - 'int16' : 'H', 36.28 - 'int32' : 'I', 36.29 - 'int64' : 'Q', 36.30 - 'u8' : 'B', 36.31 - 'u16' : 'H', 36.32 - 'u32' : 'I', 36.33 - 'u64' : 'Q' 36.34 - } 36.35 - 36.36 - def typedef(self, name, val): 36.37 - self.formats[name] = val 36.38 - 36.39 - def struct(self, name, *f): 36.40 - self.typedef(name, StructInfo(self, f)) 36.41 - 36.42 - def getType(self, name): 36.43 - return self.formats[name] 36.44 - 36.45 - def format(self, ty): 36.46 - d = 0 36.47 - f = ty 36.48 - while d < self.maxDepth: 36.49 - d += 1 36.50 - f = self.formats[f] 36.51 - if isinstance(f, StructInfo): 36.52 - return f.format() 36.53 - if f in self.base: 36.54 - return f 36.55 - return -1 36.56 - 36.57 - def alignedformat(self, ty): 36.58 - fmt = self.format(ty) 36.59 - #print 'alignedformat> %s |%s|' %(ty, fmt) 36.60 - afmt = self.align(fmt) 36.61 - #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt) 36.62 - return afmt 36.63 - 36.64 - def align(self, fmt): 36.65 - n1 = 0 36.66 - afmt = '' 36.67 - for a in fmt: 36.68 - n2 = self.getSize(a) 36.69 - m = n1 % n2 36.70 - if m: 36.71 - d = (n2 - m) 36.72 - afmt += 'x' * d 36.73 - n1 += d 36.74 - afmt += a 36.75 - n1 += n2 36.76 - return afmt 36.77 - 36.78 - def fmtsize(self, fmt): 36.79 - s = 0 36.80 - for f in fmt: 36.81 - s += self.getSize(f) 36.82 - return s 36.83 - 36.84 - def getSize(self, f): 36.85 - return self.sizes[f] 36.86 - 36.87 - def pack(self, ty, data): 36.88 - return self.getType(ty).pack(data) 36.89 - 36.90 - def unpack(self, ty, data): 36.91 - return self.getType(ty).unpack(data) 36.92 - 36.93 - def show(self): 36.94 - l = self.formats.keys() 36.95 - l.sort() 36.96 - for v in l: 36.97 - print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v)) 36.98 - 36.99 - 36.100 -class StructInfo: 36.101 - 36.102 - def __init__(self, s, f): 36.103 - self.fmt = None 36.104 - self.structs = s 36.105 - self.fields = f 36.106 - 36.107 - def alignedformat(self): 36.108 - if self.afmt: return self.afmt 36.109 - self.afmt = self.structs.align(self.format()) 36.110 - return self.afmt 36.111 - 36.112 - def format(self): 36.113 - if self.fmt: return self.fmt 36.114 - fmt = "" 36.115 - for (ty, name) in self.fields: 36.116 - fmt += self.formatString(ty) 36.117 - self.fmt = fmt 36.118 - return fmt 36.119 - 36.120 - def formatString(self, ty): 36.121 - if ty in self.fields: 36.122 - ty = self.fields[ty] 36.123 - return self.structs.format(ty) 36.124 - 36.125 - def pack(self, *args): 36.126 - return struct.pack(self.alignedformat(), *args) 36.127 - 36.128 - def unpack(self, data): 36.129 - return struct.unpack(self.alignedformat(), data) 36.130 - 36.131 -types = Struct() 36.132 - 36.133 -types.typedef('short' , 'h') 36.134 -types.typedef('int' , 'i') 36.135 -types.typedef('long' , 'l') 36.136 -types.typedef('unsigned short', 'H') 36.137 -types.typedef('unsigned int' , 'I') 36.138 -types.typedef('unsigned long' , 'L') 36.139 -types.typedef('domid_t' , 'u64') 36.140 -types.typedef('blkif_vdev_t' , 'u16') 36.141 -types.typedef('blkif_pdev_t' , 'u16') 36.142 -types.typedef('blkif_sector_t', 'u64') 36.143 - 36.144 -types.struct('u8[6]', 36.145 - ('u8', 'a1'), 36.146 - ('u8', 'a2'), 36.147 - ('u8', 'a3'), 36.148 - ('u8', 'a4'), 36.149 - ('u8', 'a5'), 36.150 - ('u8', 'a6')) 36.151 - 36.152 -types.struct('blkif_fe_interface_status_changed_t', 36.153 - ('unsigned int', 'handle'), 36.154 - ('unsigned int', 'status'), 36.155 - ('unsigned int', 'evtchn')) 36.156 - 36.157 -types.struct('blkif_fe_driver_status_changed_t', 36.158 - ('unsigned int', 'status'), 36.159 - ('unsigned int', 'nr_interfaces')) 36.160 - 36.161 -types.struct('blkif_fe_interface_connect_t', 36.162 - ('unsigned int' , 'handle'), 36.163 - ('unsigned long', 'shmem_frame')) 36.164 - 36.165 -types.struct('blkif_fe_interface_disconnect_t', 36.166 - ('unsigned int', 'handle')) 36.167 - 36.168 -types.struct('blkif_extent_t', 36.169 - ('blkif_pdev_t' , 'device'), 36.170 - ('blkif_sector_t', 'sector_start'), 36.171 - ('blkif_sector_t', 'sector_length')) 36.172 - 36.173 -types.struct('blkif_be_create_t', 36.174 - ('domid_t' , 'domid'), 36.175 - ('unsigned int', 'blkif_handle'), 36.176 - ('unsigned int', 'status')) 36.177 - 36.178 -types.struct('blkif_be_destroy_t', 36.179 - ('domid_t' , 'domid'), 36.180 - ('unsigned int', 'blkif_handle'), 36.181 - ('unsigned int', 'status')) 36.182 - 36.183 -types.struct('blkif_be_connect_t', 36.184 - ('domid_t' , 'domid'), 36.185 - ('unsigned int' , 'blkif_handle'), 36.186 - ('unsigned int' , 'evtchn'), 36.187 - ('unsigned long', 'shmem_frame'), 36.188 - ('unsigned int' , 'status')) 36.189 - 36.190 -types.struct('blkif_be_disconnect_t', 36.191 - ('domid_t' , 'domid'), 36.192 - ('unsigned int', 'blkif_handle'), 36.193 - ('unsigned int', 'status')) 36.194 - 36.195 -types.struct('blkif_be_vbd_create_t', 36.196 - ('domid_t' , 'domid'), #Q 36.197 - ('unsigned int', 'blkif_handle'), #I 36.198 - ('blkif_vdev_t', 'vdevice'), #H 36.199 - ('int' , 'readonly'), #i 36.200 - ('unsigned int', 'status')) #I 36.201 - 36.202 -types.struct('blkif_be_vbd_destroy_t', 36.203 - ('domid_t' , 'domid'), 36.204 - ('unsigned int', 'blkif_handle'), 36.205 - ('blkif_vdev_t', 'vdevice'), 36.206 - ('unsigned int', 'status')) 36.207 - 36.208 -types.struct('blkif_be_vbd_grow_t', 36.209 - ('domid_t' , 'domid'), #Q 36.210 - ('unsigned int' , 'blkif_handle'), #I 36.211 - ('blkif_vdev_t' , 'vdevice'), #H 36.212 - ('blkif_extent_t', 'extent'), #HQQ 36.213 - ('unsigned int' , 'status')) #I 36.214 - 36.215 -types.struct('blkif_be_vbd_shrink_t', 36.216 - ('domid_t' , 'domid'), 36.217 - ('unsigned int', 'blkif_handle'), 36.218 - ('blkif_vdev_t', 'vdevice'), 36.219 - ('unsigned int', 'status')) 36.220 - 36.221 -types.struct('blkif_be_driver_status_changed_t', 36.222 - ('unsigned int', 'status'), 36.223 - ('unsigned int', 'nr_interfaces')) 36.224 - 36.225 -types.struct('netif_fe_interface_status_changed_t', 36.226 - ('unsigned int', 'handle'), 36.227 - ('unsigned int', 'status'), 36.228 - ('unsigned int', 'evtchn'), 36.229 - ('u8[6]', 'mac')) 36.230 - 36.231 -types.struct('netif_fe_driver_status_changed_t', 36.232 - ('unsigned int', 'status'), 36.233 - ('unsigned int', 'nr_interfaces')) 36.234 - 36.235 -types.struct('netif_fe_interface_connect_t', 36.236 - ('unsigned int', 'handle'), 36.237 - ('unsigned long', 'tx_shmem_frame'), 36.238 - ('unsigned long', 'rx_shmem_frame')) 36.239 - 36.240 -types.struct('netif_fe_interface_disconnect_t', 36.241 - ('unsigned int', 'handle')) 36.242 - 36.243 -types.struct('netif_be_create_t', 36.244 - ('domid_t' , 'domid'), 36.245 - ('unsigned int', 'netif_handle'), 36.246 - ('u8[6]' , 'mac'), 36.247 - ('unsigned int', 'status')) 36.248 - 36.249 -types.struct('netif_be_destroy_t', 36.250 - ('domid_t' , 'domid'), 36.251 - ('unsigned int', 'netif_handle'), 36.252 - ('unsigned int', 'status')) 36.253 - 36.254 -types.struct('netif_be_connect_t', 36.255 - ('domid_t' , 'domid'), 36.256 - ('unsigned int' , 'netif_handle'), 36.257 - ('unsigned int' , 'evtchn'), 36.258 - ('unsigned long', 'tx_shmem_frame'), 36.259 - ('unsigned long', 'rx_shmem_frame'), 36.260 - ('unsigned int' , 'status')) 36.261 - 36.262 -types.struct('netif_be_disconnect_t', 36.263 - ('domid_t' , 'domid'), 36.264 - ('unsigned int', 'netif_handle'), 36.265 - ('unsigned int', 'status')) 36.266 - 36.267 -types.struct('netif_be_driver_status_changed_t', 36.268 - ('unsigned int', 'status'), 36.269 - ('unsigned int', 'nr_interfaces')) 36.270 - 36.271 -if 1 or __name__ == "__main__": 36.272 - types.show()
37.1 --- a/tools/python/xen/xend/server/domain.py Tue Jul 06 17:25:40 2004 +0000 37.2 +++ b/tools/python/xen/xend/server/domain.py Tue Jul 06 17:27:27 2004 +0000 37.3 @@ -1,3 +1,5 @@ 37.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 37.5 + 37.6 import channel 37.7 import controller 37.8 from messages import * 37.9 @@ -7,11 +9,23 @@ class DomainControllerFactory(controller 37.10 """ 37.11 37.12 def createInstance(self, dom): 37.13 + """Create a domain controller. 37.14 + 37.15 + dom domain 37.16 + 37.17 + returns domain controller 37.18 + """ 37.19 d = DomainController(self, dom) 37.20 self.addInstance(d) 37.21 return d 37.22 37.23 def getInstanceByDom(self, dom): 37.24 + """Get a domain controller for a domain, creating if necessary. 37.25 + 37.26 + dom domain 37.27 + 37.28 + returns domain controller 37.29 + """ 37.30 for inst in self.instances.values(): 37.31 if inst.dom == dom: 37.32 return inst 37.33 @@ -21,8 +35,11 @@ class DomainControllerFactory(controller 37.34 37.35 class DomainController(controller.Controller): 37.36 """Generic controller for a domain. 37.37 + Used for domain shutdown. 37.38 """ 37.39 37.40 + """Map shutdown reasons to the message type to use. 37.41 + """ 37.42 reasons = {'poweroff' : 'shutdown_poweroff_t', 37.43 'reboot' : 'shutdown_reboot_t', 37.44 'suspend' : 'shutdown_suspend_t' } 37.45 @@ -34,6 +51,10 @@ class DomainController(controller.Contro 37.46 print 'DomainController>', self, self.channel, self.idx 37.47 37.48 def shutdown(self, reason): 37.49 + """Shutdown a domain. 37.50 + 37.51 + reason shutdown reason 37.52 + """ 37.53 msgtype = self.reasons.get(reason) 37.54 if not msgtype: 37.55 raise ValueError('invalid reason:' + reason)
38.1 --- a/tools/python/xen/xend/server/messages.py Tue Jul 06 17:25:40 2004 +0000 38.2 +++ b/tools/python/xen/xend/server/messages.py Tue Jul 06 17:27:27 2004 +0000 38.3 @@ -148,6 +148,9 @@ netif_formats = { 38.4 msg_formats.update(netif_formats) 38.5 38.6 #============================================================================ 38.7 +# Domain shutdown message types. 38.8 +#============================================================================ 38.9 + 38.10 CMSG_SHUTDOWN = 6 38.11 38.12 CMSG_SHUTDOWN_POWEROFF = 0 38.13 @@ -176,8 +179,23 @@ msg_formats.update(shutdown_formats) 38.14 class Msg: 38.15 pass 38.16 38.17 +_next_msgid = 0 38.18 + 38.19 +def nextid(): 38.20 + global _next_msgid 38.21 + return ++_next_msgid 38.22 + 38.23 def packMsg(ty, params): 38.24 - if DEBUG: print '>packMsg', ty, params 38.25 + """Pack a message. 38.26 + Any 'mac' parameter is passed in as an int[6] array and converted. 38.27 + 38.28 + ty message type name 38.29 + params message parameter dict 38.30 + 38.31 + returns xu message 38.32 + """ 38.33 + msgid = nextid() 38.34 + if DEBUG: print '>packMsg', msgid, ty, params 38.35 (major, minor) = msg_formats[ty] 38.36 args = {} 38.37 for (k, v) in params.items(): 38.38 @@ -189,11 +207,19 @@ def packMsg(ty, params): 38.39 if DEBUG: 38.40 for (k, v) in args.items(): 38.41 print 'packMsg>', k, v, type(v) 38.42 - msgid = 0 38.43 msg = xu.message(major, minor, msgid, args) 38.44 return msg 38.45 38.46 def unpackMsg(ty, msg): 38.47 + """Unpack a message. 38.48 + Any mac addresses in the message are converted to int[6] array 38.49 + in the return dict. 38.50 + 38.51 + ty message type 38.52 + msg xu message 38.53 + 38.54 + returns parameter dict 38.55 + """ 38.56 args = msg.get_payload() 38.57 mac = [0, 0, 0, 0, 0, 0] 38.58 macs = [] 38.59 @@ -208,10 +234,19 @@ def unpackMsg(ty, msg): 38.60 args['mac'] = mac 38.61 for k in macs: 38.62 del args[k] 38.63 - if DEBUG: print '<unpackMsg', ty, args 38.64 + if DEBUG: 38.65 + msgid = msg.get_header()['id'] 38.66 + print '<unpackMsg', msgid, ty, args 38.67 return args 38.68 38.69 def msgTypeName(ty, subty): 38.70 + """Convert a message type, subtype pair (ints) to a message type name (string). 38.71 + 38.72 + ty integer message type 38.73 + subty integer message subtype 38.74 + 38.75 + returns message type name (or None) 38.76 + """ 38.77 for (name, info) in msg_formats.items(): 38.78 if info[0] == ty and info[1] == subty: 38.79 return name
39.1 --- a/tools/python/xen/xend/server/netif.py Tue Jul 06 17:25:40 2004 +0000 39.2 +++ b/tools/python/xen/xend/server/netif.py Tue Jul 06 17:27:27 2004 +0000 39.3 @@ -1,6 +1,9 @@ 39.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 39.5 + 39.6 import random 39.7 39.8 from twisted.internet import defer 39.9 +defer.Deferred.debug = 1 39.10 39.11 from xen.xend import sxp 39.12 from xen.xend import PrettyPrint 39.13 @@ -21,8 +24,8 @@ class NetifControllerFactory(controller. 39.14 self.majorTypes = [ CMSG_NETIF_BE ] 39.15 39.16 self.subTypes = { 39.17 - CMSG_NETIF_BE_CREATE : self.recv_be_create, 39.18 - CMSG_NETIF_BE_CONNECT: self.recv_be_connect, 39.19 + #CMSG_NETIF_BE_CREATE : self.recv_be_create, 39.20 + #CMSG_NETIF_BE_CONNECT: self.recv_be_connect, 39.21 CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed, 39.22 } 39.23 self.attached = 1 39.24 @@ -30,8 +33,12 @@ class NetifControllerFactory(controller. 39.25 39.26 def createInstance(self, dom, recreate=0): 39.27 """Create or find the network interface controller for a domain. 39.28 + 39.29 + dom domain 39.30 + recreate if true this is a recreate (xend restarted) 39.31 + 39.32 + returns netif controller 39.33 """ 39.34 - #print 'netif>createInstance> dom=', dom 39.35 netif = self.getInstanceByDom(dom) 39.36 if netif is None: 39.37 netif = NetifController(self, dom) 39.38 @@ -39,15 +46,31 @@ class NetifControllerFactory(controller. 39.39 return netif 39.40 39.41 def getDomainDevices(self, dom): 39.42 + """Get the network device controllers for a domain. 39.43 + 39.44 + dom domain 39.45 + 39.46 + returns netif controller 39.47 + """ 39.48 netif = self.getInstanceByDom(dom) 39.49 return (netif and netif.getDevices()) or [] 39.50 39.51 def getDomainDevice(self, dom, vif): 39.52 + """Get a virtual network interface device for a domain. 39.53 + 39.54 + dom domain 39.55 + vif virtual interface index 39.56 + 39.57 + returns NetDev 39.58 + """ 39.59 netif = self.getInstanceByDom(dom) 39.60 return (netif and netif.getDevice(vif)) or None 39.61 39.62 def setControlDomain(self, dom, recreate=0): 39.63 """Set the 'back-end' device driver domain. 39.64 + 39.65 + dom domain 39.66 + recreate if true this is a recreate (xend restarted) 39.67 """ 39.68 if self.dom == dom: return 39.69 self.deregisterChannel() 39.70 @@ -55,19 +78,13 @@ class NetifControllerFactory(controller. 39.71 self.attached = 0 39.72 self.dom = dom 39.73 self.registerChannel() 39.74 - # 39.75 - #if xend.netif.be_port.remote_dom != 0: 39.76 - # xend.netif.recovery = True 39.77 - # xend.netif.be_port = xend.main.port_from_dom(dom) 39.78 - # 39.79 39.80 def getControlDomain(self): 39.81 + """Get the domain id of the back-end control domain. 39.82 + """ 39.83 return self.dom 39.84 39.85 - def recv_be_create(self, msg, req): 39.86 - self.callDeferred(0) 39.87 - 39.88 - def recv_be_connect(self, msg, req): 39.89 + def respond_be_connect(self, msg): 39.90 val = unpackMsg('netif_be_connect_t', msg) 39.91 dom = val['domid'] 39.92 vif = val['netif_handle'] 39.93 @@ -75,7 +92,7 @@ class NetifControllerFactory(controller. 39.94 if netif: 39.95 netif.send_interface_connected(vif) 39.96 else: 39.97 - print "recv_be_connect> unknown vif=", vif 39.98 + print "respond_be_connect> unknown vif=", vif 39.99 pass 39.100 39.101 def recv_be_driver_status_changed(self, msg, req): 39.102 @@ -88,23 +105,6 @@ class NetifControllerFactory(controller. 39.103 netif.reattach_devices() 39.104 self.attached = 1 39.105 39.106 -## pl = msg.get_payload() 39.107 -## status = pl['status'] 39.108 -## if status == NETIF_DRIVER_STATUS_UP: 39.109 -## if xend.netif.recovery: 39.110 -## print "New netif backend now UP, notifying guests:" 39.111 -## for netif_key in interface.list.keys(): 39.112 -## netif = interface.list[netif_key] 39.113 -## netif.create() 39.114 -## print " Notifying %d" % netif.dom 39.115 -## msg = xu.message( 39.116 -## CMSG_NETIF_FE, 39.117 -## CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0, 39.118 -## { 'handle' : 0, 'status' : 1 }) 39.119 -## netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg) 39.120 -## print "Done notifying guests" 39.121 -## recovery = False 39.122 - 39.123 class NetDev(controller.Dev): 39.124 """Info record for a network device. 39.125 """ 39.126 @@ -130,9 +130,13 @@ class NetDev(controller.Dev): 39.127 return val 39.128 39.129 def get_vifname(self): 39.130 + """Get the virtual interface device name. 39.131 + """ 39.132 return "vif%d.%d" % (self.controller.dom, self.vif) 39.133 39.134 def get_mac(self): 39.135 + """Get the MAC address as a string. 39.136 + """ 39.137 return ':'.join(map(lambda x: "%x" % x, self.mac)) 39.138 39.139 def vifctl_params(self): 39.140 @@ -141,23 +145,31 @@ class NetDev(controller.Dev): 39.141 'ipaddr': self.ipaddr } 39.142 39.143 def up(self, bridge=None, ipaddr=[]): 39.144 + """Bring the device up. 39.145 + 39.146 + bridge ethernet bridge to connect to 39.147 + ipaddr list of ipaddrs to filter using iptables 39.148 + """ 39.149 self.bridge = bridge 39.150 self.ipaddr = ipaddr 39.151 Vifctl.up(self.get_vifname(), **self.vifctl_params()) 39.152 39.153 def down(self): 39.154 + """Bring the device down. 39.155 + """ 39.156 Vifctl.down(self.get_vifname(), **self.vifctl_params()) 39.157 39.158 def destroy(self): 39.159 + """Destroy the device's resources and disconnect from the back-end 39.160 + device controller. 39.161 + """ 39.162 def cb_destroy(val): 39.163 self.controller.send_be_destroy(self.vif) 39.164 - print 'NetDev>destroy>', 'vif=', self.vif 39.165 - PrettyPrint.prettyprint(self.sxpr()) 39.166 self.down() 39.167 - d = self.controller.factory.addDeferred() 39.168 + #d = self.controller.factory.addDeferred() 39.169 + d = defer.Deferred() 39.170 d.addCallback(cb_destroy) 39.171 - self.controller.send_be_disconnect(self.vif) 39.172 - #self.controller.send_be_destroy(self.vif) 39.173 + self.controller.send_be_disconnect(self.vif, response=d) 39.174 39.175 39.176 class NetifController(controller.Controller): 39.177 @@ -165,7 +177,6 @@ class NetifController(controller.Control 39.178 """ 39.179 39.180 def __init__(self, factory, dom): 39.181 - #print 'NetifController> dom=', dom 39.182 controller.Controller.__init__(self, factory, dom) 39.183 self.devices = {} 39.184 39.185 @@ -178,21 +189,23 @@ class NetifController(controller.Control 39.186 self.recv_fe_interface_connect, 39.187 } 39.188 self.registerChannel() 39.189 - #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx 39.190 39.191 def sxpr(self): 39.192 val = ['netif', ['dom', self.dom]] 39.193 return val 39.194 39.195 def randomMAC(self): 39.196 - # VIFs get a random MAC address with a "special" vendor id. 39.197 - # 39.198 - # NB. The vendor is currently an "obsolete" one that used to belong 39.199 - # to DEC (AA-00-00). Using it is probably a bit rude :-) 39.200 - # 39.201 - # NB2. The first bit of the first random octet is set to zero for 39.202 - # all dynamic MAC addresses. This may allow us to manually specify 39.203 - # MAC addresses for some VIFs with no fear of clashes. 39.204 + """Generate a random MAC address. 39.205 + 39.206 + Uses OUI (Organizationally Unique Identifier) AA:00:00, an 39.207 + unassigned one that used to belong to DEC. The OUI list is 39.208 + available at 'standards.ieee.org'. 39.209 + 39.210 + The remaining 3 fields are random, with the first bit of the first 39.211 + random field set 0. 39.212 + 39.213 + returns array of 6 ints 39.214 + """ 39.215 mac = [ 0xaa, 0x00, 0x00, 39.216 random.randint(0x00, 0x7f), 39.217 random.randint(0x00, 0xff), 39.218 @@ -200,29 +213,46 @@ class NetifController(controller.Control 39.219 return mac 39.220 39.221 def lostChannel(self): 39.222 - print 'NetifController>lostChannel>', 'dom=', self.dom 39.223 - #self.destroyDevices() 39.224 + """Method called when the channel has been lost. 39.225 + """ 39.226 controller.Controller.lostChannel(self) 39.227 39.228 def getDevices(self): 39.229 + """Get a list of the devices. 39.230 + """ 39.231 return self.devices.values() 39.232 39.233 def getDevice(self, vif): 39.234 + """Get a device. 39.235 + 39.236 + vif device index 39.237 + 39.238 + returns device (or None) 39.239 + """ 39.240 return self.devices.get(vif) 39.241 39.242 def addDevice(self, vif, vmac): 39.243 + """Add a network interface. If vmac is None a random MAC is 39.244 + assigned. If specified, vmac must be a string of the form 39.245 + XX:XX:XX:XX:XX where X is hex digit. 39.246 + 39.247 + vif device index 39.248 + vmac device MAC 39.249 + 39.250 + returns device 39.251 + """ 39.252 if vmac is None: 39.253 mac = self.randomMAC() 39.254 else: 39.255 mac = [ int(x, 16) for x in vmac.split(':') ] 39.256 if len(mac) != 6: raise ValueError("invalid mac") 39.257 - #print "attach_device>", "vif=", vif, "mac=", mac 39.258 dev = NetDev(self, vif, mac) 39.259 self.devices[vif] = dev 39.260 return dev 39.261 39.262 def destroy(self): 39.263 - print 'NetifController>destroy>', 'dom=', self.dom 39.264 + """Destroy the controller and all devices. 39.265 + """ 39.266 self.destroyDevices() 39.267 39.268 def destroyDevices(self): 39.269 @@ -237,20 +267,19 @@ class NetifController(controller.Control 39.270 @param vmac mac address (string) 39.271 """ 39.272 self.addDevice(vif, vmac) 39.273 + d = defer.Deferred() 39.274 if recreate: 39.275 - d = defer.Deferred() 39.276 d.callback(self) 39.277 else: 39.278 - d = self.factory.addDeferred() 39.279 - self.send_be_create(vif) 39.280 + self.send_be_create(vif, response=d) 39.281 return d 39.282 39.283 def reattach_devices(self): 39.284 """Reattach all devices when the back-end control domain has changed. 39.285 """ 39.286 - d = self.factory.addDeferred() 39.287 + #d = self.factory.addDeferred() 39.288 self.send_be_create(vif) 39.289 - self.attach_fe_devices(0) 39.290 + self.attach_fe_devices() 39.291 39.292 def attach_fe_devices(self): 39.293 for dev in self.devices.values(): 39.294 @@ -279,38 +308,39 @@ class NetifController(controller.Control 39.295 'evtchn' : dev.evtchn['port1'], 39.296 'tx_shmem_frame' : val['tx_shmem_frame'], 39.297 'rx_shmem_frame' : val['rx_shmem_frame'] }) 39.298 - self.factory.writeRequest(msg) 39.299 + d = defer.Deferred() 39.300 + d.addCallback(self.factory.respond_be_connect) 39.301 + self.factory.writeRequest(msg, response=d) 39.302 39.303 - def send_interface_connected(self, vif): 39.304 + def send_interface_connected(self, vif, response=None): 39.305 dev = self.devices[vif] 39.306 msg = packMsg('netif_fe_interface_status_changed_t', 39.307 { 'handle' : dev.vif, 39.308 'status' : NETIF_INTERFACE_STATUS_CONNECTED, 39.309 'evtchn' : dev.evtchn['port2'], 39.310 'mac' : dev.mac }) 39.311 - self.writeRequest(msg) 39.312 + self.writeRequest(msg, response=response) 39.313 39.314 - def send_be_create(self, vif): 39.315 + def send_be_create(self, vif, response=None): 39.316 dev = self.devices[vif] 39.317 msg = packMsg('netif_be_create_t', 39.318 { 'domid' : self.dom, 39.319 'netif_handle' : dev.vif, 39.320 'mac' : dev.mac }) 39.321 - self.factory.writeRequest(msg) 39.322 + self.factory.writeRequest(msg, response=response) 39.323 39.324 - def send_be_disconnect(self, vif): 39.325 + def send_be_disconnect(self, vif, response=None): 39.326 dev = self.devices[vif] 39.327 msg = packMsg('netif_be_disconnect_t', 39.328 { 'domid' : self.dom, 39.329 'netif_handle' : dev.vif }) 39.330 - self.factory.writeRequest(msg) 39.331 + self.factory.writeRequest(msg, response=response) 39.332 39.333 - def send_be_destroy(self, vif): 39.334 - print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif 39.335 + def send_be_destroy(self, vif, response=None): 39.336 PrettyPrint.prettyprint(self.sxpr()) 39.337 dev = self.devices[vif] 39.338 del self.devices[vif] 39.339 msg = packMsg('netif_be_destroy_t', 39.340 { 'domid' : self.dom, 39.341 'netif_handle' : vif }) 39.342 - self.factory.writeRequest(msg) 39.343 + self.factory.writeRequest(msg, response=response)
40.1 --- a/tools/python/xen/xend/sxp.py Tue Jul 06 17:25:40 2004 +0000 40.2 +++ b/tools/python/xen/xend/sxp.py Tue Jul 06 17:27:27 2004 +0000 40.3 @@ -21,56 +21,19 @@ from StringIO import StringIO 40.4 __all__ = [ 40.5 "mime_type", 40.6 "ParseError", 40.7 - "Parser", 40.8 - "atomp", 40.9 - "show", 40.10 - "show_xml", 40.11 - "elementp", 40.12 + "Parser", 40.13 + "show", 40.14 "name", 40.15 - "attributes", 40.16 - "attribute", 40.17 "children", 40.18 "child", 40.19 - "child_at", 40.20 - "child0", 40.21 - "child1", 40.22 - "child2", 40.23 - "child3", 40.24 - "child4", 40.25 "child_value", 40.26 - "has_id", 40.27 - "with_id", 40.28 - "child_with_id", 40.29 - "elements", 40.30 "to_string", 40.31 "from_string", 40.32 - "all_from_string", 40.33 "parse", 40.34 ] 40.35 40.36 mime_type = "application/sxp" 40.37 40.38 -escapes = { 40.39 - 'a': '\a', 40.40 - 'b': '\b', 40.41 - 't': '\t', 40.42 - 'n': '\n', 40.43 - 'v': '\v', 40.44 - 'f': '\f', 40.45 - 'r': '\r', 40.46 - '\\': '\\', 40.47 - '\'': '\'', 40.48 - '\"': '\"'} 40.49 - 40.50 -k_list_open = "(" 40.51 -k_list_close = ")" 40.52 -k_attr_open = "@" 40.53 -k_eval = "!" 40.54 - 40.55 -escapes_rev = {} 40.56 -for k in escapes: 40.57 - escapes_rev[escapes[k]] = k 40.58 - 40.59 class ParseError(StandardError): 40.60 40.61 def __init__(self, parser, value): 40.62 @@ -86,7 +49,6 @@ class ParserState: 40.63 self.parent = parent 40.64 self.buf = '' 40.65 self.val = [] 40.66 - self.delim = None 40.67 self.fn = fn 40.68 40.69 def push(self, fn): 40.70 @@ -95,28 +57,19 @@ class ParserState: 40.71 class Parser: 40.72 40.73 def __init__(self): 40.74 - self.error = sys.stderr 40.75 self.reset() 40.76 40.77 def reset(self): 40.78 - self.val = [] 40.79 self.eof = 0 40.80 - self.err = 0 40.81 self.line_no = 0 40.82 self.char_no = 0 40.83 - self.state = None 40.84 + self.state = self.start_state = ParserState(self.state_start) 40.85 40.86 def push_state(self, fn): 40.87 self.state = self.state.push(fn) 40.88 40.89 def pop_state(self): 40.90 - val = self.state 40.91 self.state = self.state.parent 40.92 - if self.state and self.state.fn == self.state_start: 40.93 - # Return to start state - produce the value. 40.94 - self.val += self.state.val 40.95 - self.state.val = [] 40.96 - return val 40.97 40.98 def in_class(self, c, s): 40.99 return s.find(c) >= 0 40.100 @@ -136,12 +89,6 @@ class Parser: 40.101 def in_printable_class(self, c): 40.102 return self.in_class(c, string.printable) 40.103 40.104 - def set_error_stream(self, error): 40.105 - self.error = error 40.106 - 40.107 - def has_error(self): 40.108 - return self.err > 0 40.109 - 40.110 def at_eof(self): 40.111 return self.eof 40.112 40.113 @@ -166,439 +113,131 @@ class Parser: 40.114 self.char_no += 1 40.115 40.116 if self.state is None: 40.117 - self.begin_start(None) 40.118 + self.state = ParserState(self.state_start) 40.119 + 40.120 self.state.fn(c) 40.121 40.122 def ready(self): 40.123 - return len(self.val) > 0 40.124 + return len(self.start_state.val) > 0 40.125 40.126 def get_val(self): 40.127 - v = self.val[0] 40.128 - self.val = self.val[1:] 40.129 + v = self.start_state.val[0] 40.130 + self.start_state.val = self.start_state.val[1:] 40.131 return v 40.132 40.133 def get_all(self): 40.134 - return self.val 40.135 - 40.136 - def begin_start(self, c): 40.137 - self.state = ParserState(self.state_start) 40.138 + return self.start_state.val 40.139 40.140 - def end_start(self): 40.141 - self.val += self.state.val 40.142 - self.pop_state() 40.143 - 40.144 def state_start(self, c): 40.145 - if self.at_eof(): 40.146 - self.end_start() 40.147 - elif self.in_space_class(c): 40.148 + if self.at_eof() or self.in_space_class(c): 40.149 pass 40.150 elif self.in_comment_class(c): 40.151 - self.begin_comment(c) 40.152 - elif c == k_list_open: 40.153 - self.begin_list(c) 40.154 - elif c == k_list_close: 40.155 + self.push_state(self.state_comment) 40.156 + elif c == '(': 40.157 + self.push_state(self.state_list) 40.158 + elif c == ')': 40.159 raise ParseError(self, "syntax error: "+c) 40.160 elif self.in_string_quote_class(c): 40.161 - self.begin_string(c) 40.162 + self.push_state(self.state_string) 40.163 + self.state.buf = c 40.164 elif self.in_printable_class(c): 40.165 - self.begin_atom(c) 40.166 + self.push_state(self.state_atom) 40.167 + self.state.buf = c 40.168 elif c == chr(4): 40.169 # ctrl-D, EOT: end-of-text. 40.170 self.input_eof() 40.171 else: 40.172 raise ParseError(self, "invalid character: code %d" % ord(c)) 40.173 40.174 - def begin_comment(self, c): 40.175 - self.push_state(self.state_comment) 40.176 - self.state.buf += c 40.177 - 40.178 - def end_comment(self): 40.179 - self.pop_state() 40.180 - 40.181 def state_comment(self, c): 40.182 if c == '\n' or self.at_eof(): 40.183 - self.end_comment() 40.184 - else: 40.185 - self.state.buf += c 40.186 + self.pop_state() 40.187 40.188 - def begin_string(self, c): 40.189 - self.push_state(self.state_string) 40.190 - self.state.delim = c 40.191 - 40.192 - def end_string(self): 40.193 - val = self.state.buf 40.194 - self.state.parent.val.append(val) 40.195 - self.pop_state() 40.196 - 40.197 def state_string(self, c): 40.198 if self.at_eof(): 40.199 raise ParseError(self, "unexpected EOF") 40.200 - elif c == self.state.delim: 40.201 - self.end_string() 40.202 - elif c == '\\': 40.203 - self.push_state(self.state_escape) 40.204 + self.state.buf += c 40.205 + # Look out for non-escaped end delimiter 40.206 + if self.state.buf[0] == c and self.state.buf[-2] != '\\': 40.207 + try: # parse escape sequences but fall back to something simple 40.208 + val = eval(compile(self.state.buf,'','eval')) 40.209 + except: 40.210 + val = self.state.buf[1:-1] # just strip the delimiters 40.211 + self.state.parent.val.append(val) 40.212 + self.pop_state() 40.213 + 40.214 + def state_atom(self, c): 40.215 + if (self.at_eof() or 40.216 + self.is_separator(c) or 40.217 + self.in_space_class(c) or 40.218 + self.in_comment_class(c)): 40.219 + val = self.state.buf 40.220 + self.state.parent.val.append(val) 40.221 + self.pop_state() 40.222 + if not self.at_eof(): 40.223 + self.input_char(c) 40.224 else: 40.225 self.state.buf += c 40.226 40.227 - def state_escape(self, c): 40.228 - if self.at_eof(): 40.229 - raise ParseError(self, "unexpected EOF") 40.230 - d = escapes.get(c) 40.231 - if d: 40.232 - self.state.parent.buf += d 40.233 - self.pop_state() 40.234 - elif c == 'x': 40.235 - self.state.fn = self.state_hex 40.236 - self.state.val = 0 40.237 - else: 40.238 - self.state.fn = self.state_octal 40.239 - self.state.val = 0 40.240 - self.input_char(c) 40.241 - 40.242 - def state_octal(self, c): 40.243 - def octaldigit(c): 40.244 - self.state.val *= 8 40.245 - self.state.val += ord(c) - ord('0') 40.246 - self.state.buf += c 40.247 - if self.state.val < 0 or self.state.val > 0xff: 40.248 - raise ParseError(self, "invalid octal escape: out of range " + self.state.buf) 40.249 - if len(self.state.buf) == 3: 40.250 - octaldone() 40.251 - 40.252 - def octaldone(): 40.253 - d = chr(self.state.val) 40.254 - self.state.parent.buf += d 40.255 - self.pop_state() 40.256 - 40.257 - if self.at_eof(): 40.258 - raise ParseError(self, "unexpected EOF") 40.259 - elif '0' <= c <= '7': 40.260 - octaldigit(c) 40.261 - elif len(self.buf): 40.262 - octaldone() 40.263 - self.input_char(c) 40.264 - 40.265 - def state_hex(self, c): 40.266 - def hexdone(): 40.267 - d = chr(self.state.val) 40.268 - self.state.parent.buf += d 40.269 - self.pop_state() 40.270 - 40.271 - def hexdigit(c, d): 40.272 - self.state.val *= 16 40.273 - self.state.val += ord(c) - ord(d) 40.274 - self.state.buf += c 40.275 - if self.state.val < 0 or self.state.val > 0xff: 40.276 - raise ParseError(self, "invalid hex escape: out of range " + self.state.buf) 40.277 - if len(self.state.buf) == 2: 40.278 - hexdone() 40.279 - 40.280 - if self.at_eof(): 40.281 - raise ParseError(self, "unexpected EOF") 40.282 - elif '0' <= c <= '9': 40.283 - hexdigit(c, '0') 40.284 - elif 'A' <= c <= 'F': 40.285 - hexdigit(c, 'A') 40.286 - elif 'a' <= c <= 'f': 40.287 - hexdigit(c, 'a') 40.288 - elif len(buf): 40.289 - hexdone() 40.290 - self.input_char(c) 40.291 - 40.292 - def begin_atom(self, c): 40.293 - self.push_state(self.state_atom) 40.294 - self.state.buf = c 40.295 - 40.296 - def end_atom(self): 40.297 - val = self.state.buf 40.298 - self.state.parent.val.append(val) 40.299 - self.pop_state() 40.300 - 40.301 - def state_atom(self, c): 40.302 - if self.at_eof(): 40.303 - self.end_atom() 40.304 - elif (self.is_separator(c) or 40.305 - self.in_space_class(c) or 40.306 - self.in_comment_class(c)): 40.307 - self.end_atom() 40.308 - self.input_char(c) 40.309 - else: 40.310 - self.state.buf += c 40.311 - 40.312 - def begin_list(self, c): 40.313 - self.push_state(self.state_list) 40.314 - 40.315 - def end_list(self): 40.316 - val = self.state.val 40.317 - self.state.parent.val.append(val) 40.318 - self.pop_state() 40.319 - 40.320 def state_list(self, c): 40.321 if self.at_eof(): 40.322 raise ParseError(self, "unexpected EOF") 40.323 - elif c == k_list_close: 40.324 - self.end_list() 40.325 + elif c == ')': 40.326 + val = self.state.val 40.327 + self.state.parent.val.append(val) 40.328 + self.pop_state() 40.329 else: 40.330 self.state_start(c) 40.331 40.332 -def atomp(sxpr): 40.333 - """Check if an sxpr is an atom. 40.334 - """ 40.335 - if sxpr.isalnum() or sxpr == '@': 40.336 - return 1 40.337 - for c in sxpr: 40.338 - if c in string.whitespace: return 0 40.339 - if c in '"\'\\(){}[]<>$#&%^': return 0 40.340 - if c in string.ascii_letters: continue 40.341 - if c in string.digits: continue 40.342 - if c in '.-_:/~': continue 40.343 - return 0 40.344 - return 1 40.345 - 40.346 def show(sxpr, out=sys.stdout): 40.347 """Print an sxpr in bracketed (lisp-style) syntax. 40.348 """ 40.349 if isinstance(sxpr, types.ListType): 40.350 - out.write(k_list_open) 40.351 - i = 0 40.352 + out.write('(') 40.353 for x in sxpr: 40.354 - if i: out.write(' ') 40.355 show(x, out) 40.356 - i += 1 40.357 - out.write(k_list_close) 40.358 - elif isinstance(sxpr, types.StringType) and atomp(sxpr): 40.359 - out.write(sxpr) 40.360 + out.write(' ') 40.361 + out.write(')') 40.362 else: 40.363 - #out.write("'" + str(sxpr) + "'") 40.364 out.write(repr(str(sxpr))) 40.365 40.366 -def show_xml(sxpr, out=sys.stdout): 40.367 - """Print an sxpr in XML syntax. 40.368 - """ 40.369 - if isinstance(sxpr, types.ListType): 40.370 - element = name(sxpr) 40.371 - out.write('<%s' % element) 40.372 - for attr in attributes(sxpr): 40.373 - out.write(' %s=%s' % (attr[0], attr[1])) 40.374 - out.write('>') 40.375 - i = 0 40.376 - for x in children(sxpr): 40.377 - if i: out.write(' ') 40.378 - show_xml(x, out) 40.379 - i += 1 40.380 - out.write('</%s>' % element) 40.381 - elif isinstance(sxpr, types.StringType) and atomp(sxpr): 40.382 - out.write(sxpr) 40.383 - else: 40.384 - out.write(str(sxpr)) 40.385 - 40.386 -def elementp(sxpr, elt=None): 40.387 - """Check if an sxpr is an element of the given type. 40.388 - 40.389 - sxpr sxpr 40.390 - elt element type 40.391 - """ 40.392 - return (isinstance(sxpr, types.ListType) 40.393 - and len(sxpr) 40.394 - and (None == elt or sxpr[0] == elt)) 40.395 - 40.396 def name(sxpr): 40.397 - """Get the element name of an sxpr. 40.398 - If the sxpr is not an element (i.e. it's an atomic value) its name 40.399 - is None. 40.400 - 40.401 - sxpr 40.402 - 40.403 - returns name (None if not an element). 40.404 - """ 40.405 - val = None 40.406 - if isinstance(sxpr, types.StringType): 40.407 - val = sxpr 40.408 - elif isinstance(sxpr, types.ListType) and len(sxpr): 40.409 - val = sxpr[0] 40.410 - return val 40.411 - 40.412 -def attributes(sxpr): 40.413 - """Get the attribute list of an sxpr. 40.414 - 40.415 - sxpr 40.416 - 40.417 - returns attribute list 40.418 + """Get the element name of an sxpr, or None if a bad sxpr. 40.419 """ 40.420 - val = [] 40.421 - if isinstance(sxpr, types.ListType) and len(sxpr) > 1: 40.422 - attr = sxpr[1] 40.423 - if elementp(attr, k_attr_open): 40.424 - val = attr[1:] 40.425 - return val 40.426 - 40.427 -def attribute(sxpr, key, val=None): 40.428 - """Get an attribute of an sxpr. 40.429 - 40.430 - sxpr sxpr 40.431 - key attribute key 40.432 - val default value (default None) 40.433 - 40.434 - returns attribute value 40.435 - """ 40.436 - for x in attributes(sxpr): 40.437 - if x[0] == key: 40.438 - val = x[1] 40.439 - break 40.440 - return val 40.441 + if isinstance(sxpr, types.StringType): 40.442 + return sxpr 40.443 + if isinstance(sxpr, types.ListType) and len(sxpr): 40.444 + return sxpr[0] 40.445 + return None 40.446 40.447 def children(sxpr, elt=None): 40.448 - """Get children of an sxpr. 40.449 - 40.450 - sxpr sxpr 40.451 - elt optional element type to filter by 40.452 - 40.453 - returns children (filtered by elt if specified) 40.454 + """Get children of an s-expression @sxpr, optionally filtered by 40.455 + element type @elt. 40.456 """ 40.457 - val = [] 40.458 - if isinstance(sxpr, types.ListType) and len(sxpr) > 1: 40.459 - i = 1 40.460 - x = sxpr[i] 40.461 - if elementp(x, k_attr_open): 40.462 - i += 1 40.463 - val = sxpr[i : ] 40.464 + if not isinstance(sxpr, types.ListType): return [] 40.465 + val = filter(lambda x: isinstance(x, types.ListType) and len(x) > 0, sxpr) 40.466 if elt: 40.467 - def iselt(x): 40.468 - return elementp(x, elt) 40.469 - val = filter(iselt, val) 40.470 + val = filter(lambda x,y=elt: x[0] == y, val) 40.471 return val 40.472 40.473 -def child(sxpr, elt, val=None): 40.474 - """Get the first child of the given element type. 40.475 - 40.476 - sxpr sxpr 40.477 - elt element type 40.478 - val default value 40.479 - """ 40.480 - for x in children(sxpr): 40.481 - if elementp(x, elt): 40.482 - val = x 40.483 - break 40.484 - return val 40.485 - 40.486 -def child_at(sxpr, index, val=None): 40.487 - """Get the child at the given index (zero-based). 40.488 - 40.489 - sxpr sxpr 40.490 - index index 40.491 - val default value 40.492 - """ 40.493 - kids = children(sxpr) 40.494 - if len(kids) > index: 40.495 - val = kids[index] 40.496 - return val 40.497 - 40.498 -def child0(sxpr, val=None): 40.499 - """Get the zeroth child. 40.500 +def child(sxpr, elt=None, idx=0): 40.501 + """Get the @idx'th child of the optional filtering type @elt in @sxpr. 40.502 """ 40.503 - return child_at(sxpr, 0, val) 40.504 - 40.505 -def child1(sxpr, val=None): 40.506 - """Get the first child. 40.507 - """ 40.508 - return child_at(sxpr, 1, val) 40.509 - 40.510 -def child2(sxpr, val=None): 40.511 - """Get the second child. 40.512 - """ 40.513 - return child_at(sxpr, 2, val) 40.514 - 40.515 -def child3(sxpr, val=None): 40.516 - """Get the third child. 40.517 - """ 40.518 - return child_at(sxpr, 3, val) 40.519 - 40.520 -def child4(sxpr, val=None): 40.521 - """Get the fourth child. 40.522 - """ 40.523 - return child_at(sxpr, 4, val) 40.524 - 40.525 -def child_value(sxpr, elt, val=None): 40.526 - """Get the value of the first child of the given element type. 40.527 - Assumes the child has an atomic value. 40.528 - 40.529 - sxpr sxpr 40.530 - elt element type 40.531 - val default value 40.532 - """ 40.533 - kid = child(sxpr, elt) 40.534 - if kid: 40.535 - val = child_at(kid, 0, val) 40.536 - return val 40.537 + x = children(sxpr, elt) 40.538 + if len(x) > idx: 40.539 + return x[idx] 40.540 + return None 40.541 40.542 -def has_id(sxpr, id): 40.543 - """Test if an s-expression has a given id. 40.544 - """ 40.545 - return attribute(sxpr, 'id') == id 40.546 - 40.547 -def with_id(sxpr, id, val=None): 40.548 - """Find the first s-expression with a given id, at any depth. 40.549 - 40.550 - sxpr s-exp or list 40.551 - id id 40.552 - val value if not found (default None) 40.553 - 40.554 - return s-exp or val 40.555 +def child_value(sxpr, elt=None): 40.556 + """Get the value of the first child of @sxpr with the optional type @elt. 40.557 """ 40.558 - if isinstance(sxpr, types.ListType): 40.559 - for n in sxpr: 40.560 - if has_id(n, id): 40.561 - val = n 40.562 - break 40.563 - v = with_id(n, id) 40.564 - if v is None: continue 40.565 - val = v 40.566 - break 40.567 - return val 40.568 - 40.569 -def child_with_id(sxpr, id, val=None): 40.570 - """Find the first child with a given id. 40.571 - 40.572 - sxpr s-exp or list 40.573 - id id 40.574 - val value if not found (default None) 40.575 - 40.576 - return s-exp or val 40.577 - """ 40.578 - if isinstance(sxpr, types.ListType): 40.579 - for n in sxpr: 40.580 - if has_id(n, id): 40.581 - val = n 40.582 - break 40.583 - return val 40.584 - 40.585 -def elements(sxpr, ctxt=None): 40.586 - """Generate elements (at any depth). 40.587 - Visit elements in pre-order. 40.588 - Values generated are (node, context) 40.589 - The context is None if there is no parent, otherwise 40.590 - (index, parent, context) where index is the node's index w.r.t its parent, 40.591 - and context is the parent's context. 40.592 - 40.593 - sxpr s-exp 40.594 - 40.595 - returns generator 40.596 - """ 40.597 - yield (sxpr, ctxt) 40.598 - i = 0 40.599 - for n in children(sxpr): 40.600 - if isinstance(n, types.ListType): 40.601 - # Calling elements() recursively does not generate recursively, 40.602 - # it just returns a generator object. So we must iterate over it. 40.603 - for v in elements(n, (i, sxpr, ctxt)): 40.604 - yield v 40.605 - i += 1 40.606 + x = child(sxpr, elt) 40.607 + if not isinstance(x, types.ListType) or len(x) < 2: 40.608 + return None 40.609 + return x[1] 40.610 40.611 def to_string(sxpr): 40.612 - """Convert an sxpr to a string. 40.613 - 40.614 - sxpr sxpr 40.615 - returns string 40.616 + """Convert an s-expression @sxpr to a string. 40.617 """ 40.618 io = StringIO() 40.619 show(sxpr, io) 40.620 @@ -608,35 +247,14 @@ def to_string(sxpr): 40.621 return val 40.622 40.623 def from_string(str): 40.624 - """Create an sxpr by parsing a string. 40.625 - 40.626 - str string 40.627 - returns sxpr 40.628 - """ 40.629 - io = StringIO(str) 40.630 - vals = parse(io) 40.631 - if vals is []: 40.632 - return None 40.633 - else: 40.634 - return vals[0] 40.635 - 40.636 - 40.637 -def all_from_string(str): 40.638 - """Create an sxpr list by parsing a string. 40.639 - 40.640 - str string 40.641 - returns sxpr list 40.642 + """Create an sxpr list from a given input string @str. 40.643 """ 40.644 io = StringIO(str) 40.645 vals = parse(io) 40.646 return vals 40.647 40.648 def parse(io): 40.649 - """Completely parse all input from 'io'. 40.650 - 40.651 - io input file object 40.652 - returns list of values, None if incomplete 40.653 - raises ParseError on parse error 40.654 + """Completely parse all input from file @io. 40.655 """ 40.656 pin = Parser() 40.657 while 1: 40.658 @@ -649,19 +267,11 @@ def parse(io): 40.659 else: 40.660 val = None 40.661 return val 40.662 + 40.663 40.664 - 40.665 if __name__ == '__main__': 40.666 - print ">main" 40.667 pin = Parser() 40.668 - while 1: 40.669 - buf = sys.stdin.read(1024) 40.670 - #buf = sys.stdin.readline() 40.671 - pin.input(buf) 40.672 - while pin.ready(): 40.673 - val = pin.get_val() 40.674 - print 40.675 - print '****** val=', val 40.676 - if len(buf) == 0: 40.677 - break 40.678 - 40.679 + buf = sys.stdin.read(1024) 40.680 + pin.input(buf) 40.681 + while pin.ready(): 40.682 + print '\n****** val=', pin.get_val()
41.1 --- a/tools/python/xen/xm/create.py Tue Jul 06 17:25:40 2004 +0000 41.2 +++ b/tools/python/xen/xm/create.py Tue Jul 06 17:27:27 2004 +0000 41.3 @@ -1,4 +1,5 @@ 41.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 41.5 + 41.6 """Domain creation. 41.7 """ 41.8 import string 41.9 @@ -15,12 +16,22 @@ from xen.xm.opts import * 41.10 gopts = Opts(use="""[options] 41.11 41.12 Create a domain. 41.13 + 41.14 +Domain creation parameters can be set by command-line switches, from 41.15 +a python configuration script or an SXP config file. See documentation 41.16 +for --defaults, --config. Configuration variables can be set using 41.17 +VAR=VAL on the command line. For example vmid=3 sets vmid to 3. 41.18 + 41.19 """) 41.20 41.21 gopts.opt('help', short='h', 41.22 fn=set_true, default=0, 41.23 use="Print this help.") 41.24 41.25 +gopts.opt('help_config', 41.26 + fn=set_true, default=0, 41.27 + use="Print help for configuration file.") 41.28 + 41.29 gopts.opt('quiet', short='q', 41.30 fn=set_true, default=0, 41.31 use="Quiet.") 41.32 @@ -31,24 +42,40 @@ gopts.opt('path', val='PATH', 41.33 41.34 gopts.opt('defaults', short='f', val='FILE', 41.35 fn=set_value, default='xmdefaults', 41.36 - use="Use the given default script.") 41.37 + use="""Use the given Python defaults script. 41.38 +The defaults script is loaded after arguments have been processed. 41.39 +Each command-line option sets a configuration variable named after 41.40 +its long option name, and these variables are placed in the 41.41 +environment of the script before it is loaded. 41.42 +Variables for options that may be repeated have list values. 41.43 +Other variables can be set using VAR=VAL on the command line. 41.44 + 41.45 +After the script is loaded, option values that were not set on the 41.46 +command line are replaced by the values set in the script. 41.47 +""") 41.48 41.49 gopts.opt('config', short='F', val='FILE', 41.50 fn=set_value, default=None, 41.51 - use='Domain configuration to use (SXP).') 41.52 + use="""Domain configuration to use (SXP). 41.53 +SXP is the underlying configuration format used by Xen. 41.54 +SXP configs can be hand-written or generated from Python defaults 41.55 +scripts, using the -n (dryrun) option to print the config. 41.56 +""") 41.57 41.58 gopts.opt('load', short='L', val='FILE', 41.59 fn=set_value, default=None, 41.60 use='Domain saved state to load.') 41.61 41.62 -gopts.opt('define', short='D', val='VAR=VAL', 41.63 - fn=set_var, default=None, 41.64 - use="""Set a variable before loading defaults, e.g. '-D vmid=3' 41.65 - to set vmid. May be repeated to set more thanone variable.""") 41.66 +#gopts.opt('define', short='D', val='VAR=VAL', 41.67 +# fn=set_var, default=None, 41.68 +# use="""Set a variable before loading defaults, e.g. '-D vmid=3' 41.69 +# to set vmid. May be repeated to set more than one variable.""") 41.70 41.71 gopts.opt('dryrun', short='n', 41.72 fn=set_true, default=0, 41.73 - use="Dry run - print the config but don't create the domain.") 41.74 + use="""Dry run - print the config but don't create the domain. 41.75 +The defaults file is loaded and the SXP configuration is created and printed. 41.76 +""") 41.77 41.78 gopts.opt('name', short='N', val='NAME', 41.79 fn=set_value, default=None, 41.80 @@ -74,6 +101,10 @@ gopts.opt('memory', short='m', val='MEMO 41.81 fn=set_value, default=128, 41.82 use="Domain memory in MB.") 41.83 41.84 +gopts.opt('autorestart', 41.85 + fn=set_true, default=0, 41.86 + use="Whether to restart the domain on exit.") 41.87 + 41.88 gopts.opt('blkif', 41.89 fn=set_true, default=0, 41.90 use="Make the domain a block device backend.") 41.91 @@ -244,6 +275,8 @@ def make_config(opts): 41.92 config.append(['backend', ['blkif']]) 41.93 if opts.netif: 41.94 config.append(['backend', ['netif']]) 41.95 + if opts.autorestart: 41.96 + config.append(['autorestart']) 41.97 41.98 configure_image(config, opts) 41.99 config_devs = [] 41.100 @@ -352,7 +385,15 @@ def main(argv): 41.101 args = opts.parse(argv) 41.102 if opts.vals.help: 41.103 opts.usage() 41.104 + if opts.vals.help or opts.vals.help_config: 41.105 + opts.load_defaults(help=1) 41.106 + if opts.vals.help or opts.vals.help_config: 41.107 return 41.108 + # Process remaining args as config variables. 41.109 + for arg in args: 41.110 + if '=' in arg: 41.111 + (var, val) = arg.strip().split('=') 41.112 + gopts.setvar(var.strip(), val.strip()) 41.113 if opts.vals.config: 41.114 pass 41.115 else:
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/tools/python/xen/xm/help.py Tue Jul 06 17:27:27 2004 +0000 42.3 @@ -0,0 +1,82 @@ 42.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 42.5 + 42.6 +"""Variable definition and help support for Python defaults files. 42.7 +""" 42.8 + 42.9 +import sys 42.10 + 42.11 +class Vars: 42.12 + """A set of configuration variables. 42.13 + """ 42.14 + 42.15 + def __init__(self, name, help, env): 42.16 + """Create a variable set. 42.17 + 42.18 + name name of the defaults file 42.19 + help help flag 42.20 + env local environment 42.21 + """ 42.22 + self.name = name 42.23 + self.help = help 42.24 + self.env = env 42.25 + self.vars = [] 42.26 + 42.27 + def var(self, name, use=None, check=None): 42.28 + """Define a configuration variable. 42.29 + If provided, the check function will be called as check(var, val) 42.30 + where var is the variable name and val is its value (string). 42.31 + It should return a new value for the variable, or raise ValueError if 42.32 + the value is not acceptable. 42.33 + 42.34 + name variable name 42.35 + use variable usage string 42.36 + check variable check function 42.37 + """ 42.38 + self.vars.append(Var(name, use, check)) 42.39 + 42.40 + def check(self): 42.41 + """Execute the variable checks or print help, depending on the value 42.42 + of the help flag passed to the constructor. 42.43 + """ 42.44 + if self.help: 42.45 + self.doHelp() 42.46 + else: 42.47 + for v in self.vars: 42.48 + v.doCheck(self.env) 42.49 + 42.50 + def doHelp(self, out=sys.stderr): 42.51 + """Print help for the variables. 42.52 + """ 42.53 + if self.vars: 42.54 + print >>out, "\nConfiguration variables for %s:\n" % self.name 42.55 + for v in self.vars: 42.56 + v.doHelp(out) 42.57 + print >>out 42.58 + 42.59 +class Var: 42.60 + """A single variable. 42.61 + """ 42.62 + 42.63 + def __init__(self, name, use, check): 42.64 + """Create a variable. 42.65 + 42.66 + name variable name 42.67 + use variable use string 42.68 + check variable value check function 42.69 + """ 42.70 + self.name = name 42.71 + self.use = use or '' 42.72 + self.check = check 42.73 + 42.74 + def doCheck(self, env): 42.75 + """Execute the check and set the variable to the new value. 42.76 + """ 42.77 + if not self.check: return 42.78 + env[self.name] = self.check(self.name, env.get(self.name)) 42.79 + 42.80 + def doHelp(self, out): 42.81 + """Print help for the variable. 42.82 + """ 42.83 + print >>out, "%-12s" % self.name, self.use 42.84 + 42.85 +
43.1 --- a/tools/python/xen/xm/main.py Tue Jul 06 17:25:40 2004 +0000 43.2 +++ b/tools/python/xen/xm/main.py Tue Jul 06 17:27:27 2004 +0000 43.3 @@ -5,10 +5,12 @@ import os 43.4 import os.path 43.5 import sys 43.6 from getopt import getopt 43.7 +import socket 43.8 43.9 from xen.xend import PrettyPrint 43.10 from xen.xend import sxp 43.11 from xen.xend.XendClient import server 43.12 +from xen.xend.XendClient import main as xend_client_main 43.13 from xen.xm import create, shutdown 43.14 43.15 class Prog: 43.16 @@ -65,6 +67,13 @@ class Xm: 43.17 sys.exit(1) 43.18 43.19 def main(self, args): 43.20 + try: 43.21 + self.main_call(args) 43.22 + except socket.error, ex: 43.23 + print >>sys.stderr, ex 43.24 + self.err("Error connecting to xend, is xend running?") 43.25 + 43.26 + def main_call(self, args): 43.27 """Main entry point. Dispatches to the progs. 43.28 """ 43.29 self.name = args[0] 43.30 @@ -237,11 +246,11 @@ class ProgList(Prog): 43.31 info = server.xend_domain(dom) 43.32 d = {} 43.33 d['dom'] = int(dom) 43.34 - d['name'] = sxp.child_value(info, 'name', '??') 43.35 - d['mem'] = int(sxp.child_value(info, 'memory', '0')) 43.36 - d['cpu'] = int(sxp.child_value(info, 'cpu', '0')) 43.37 - d['state'] = sxp.child_value(info, 'state', '??') 43.38 - d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0')) 43.39 + d['name'] = sxp.child_value(info, 'name') or '??' 43.40 + d['mem'] = int(sxp.child_value(info, 'memory') or '-1') 43.41 + d['cpu'] = int(sxp.child_value(info, 'cpu') or '-1') 43.42 + d['state'] = sxp.child_value(info, 'state') or '??' 43.43 + d['cpu_time'] = float(sxp.child_value(info, 'cpu_time') or '-1') 43.44 print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f" % d) 43.45 43.46 def long_list(self, doms): 43.47 @@ -415,9 +424,9 @@ class ProgConsoles(Prog): 43.48 for x in l: 43.49 info = server.xend_console(x) 43.50 d = {} 43.51 - d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1] 43.52 - d['port'] = sxp.child_value(info, 'port', '?') 43.53 - d['id'] = sxp.child_value(info, 'id', '?') 43.54 + d['dom'] = (sxp.child(info, 'dst') or ['dst', '?', '?'])[1] 43.55 + d['port'] = sxp.child_value(info, 'port') or '?' 43.56 + d['id'] = sxp.child_value(info, 'id') or '?' 43.57 print "%(dom)3s %(port)4s %(id)3s" % d 43.58 43.59 xm.prog(ProgConsoles) 43.60 @@ -444,5 +453,21 @@ class ProgConsole(Prog): 43.61 43.62 xm.prog(ProgConsole) 43.63 43.64 +class ProgCall(Prog): 43.65 + name = "call" 43.66 + info = "Call xend api functions." 43.67 + 43.68 + def help (self, args): 43.69 + print "call fn argss..." 43.70 + print """ 43.71 + Call a xend HTTP API function. The leading 'xend_' on the function 43.72 +can be omitted. See xen.xend.XendClient for the API functions. 43.73 +""" 43.74 + 43.75 + def main(self, args): 43.76 + xend_client_main(args) 43.77 + 43.78 +xm.prog(ProgCall) 43.79 + 43.80 def main(args): 43.81 xm.main(args)
44.1 --- a/tools/python/xen/xm/opts.py Tue Jul 06 17:25:40 2004 +0000 44.2 +++ b/tools/python/xen/xm/opts.py Tue Jul 06 17:27:27 2004 +0000 44.3 @@ -259,7 +259,7 @@ class Opts: 44.4 for opt in self.options: 44.5 opt.show() 44.6 44.7 - def load_defaults(self): 44.8 + def load_defaults(self, help=0): 44.9 """Load a defaults script. Assumes these options set: 44.10 'path' search path 44.11 'default' script name 44.12 @@ -270,12 +270,12 @@ class Opts: 44.13 else: 44.14 p = self.vals.defaults 44.15 if os.path.exists(p): 44.16 - self.load(p) 44.17 + self.load(p, help) 44.18 break 44.19 else: 44.20 self.err("Cannot open defaults file %s" % self.vals.defaults) 44.21 44.22 - def load(self, defaults, help=0): 44.23 + def load(self, defaults, help): 44.24 """Load a defaults file. Local variables in the file 44.25 are used to set options with the same names. 44.26 Variables are not used to set options that are already specified. 44.27 @@ -290,11 +290,17 @@ class Opts: 44.28 cmd = '\n'.join(["import sys", 44.29 "import os", 44.30 "import os.path", 44.31 - "import xen.util.ip", 44.32 + "from xen.xm.help import Vars", 44.33 + "from xen.util import ip", 44.34 "xm_file = '%s'" % defaults, 44.35 - "xm_help = %d" % help ]) 44.36 + "xm_help = %d" % help, 44.37 + "xm_vars = Vars(xm_file, xm_help, locals())", 44.38 + ]) 44.39 exec cmd in globals, locals 44.40 - execfile(defaults, globals, locals) 44.41 + try: 44.42 + execfile(defaults, globals, locals) 44.43 + except: 44.44 + if not help: raise 44.45 if help: return 44.46 # Extract the values set by the script and set the corresponding 44.47 # options, if not set on the command line.
45.1 --- a/tools/python/xen/xm/shutdown.py Tue Jul 06 17:25:40 2004 +0000 45.2 +++ b/tools/python/xen/xm/shutdown.py Tue Jul 06 17:27:27 2004 +0000 45.3 @@ -1,4 +1,5 @@ 45.4 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 45.5 + 45.6 """Domain shutdown. 45.7 """ 45.8 import string 45.9 @@ -10,7 +11,8 @@ from xen.xm.opts import * 45.10 45.11 gopts = Opts(use="""[options] [DOM] 45.12 45.13 -Shutdown one or more domains gracefully.""") 45.14 +Shutdown one or more domains gracefully. 45.15 +""") 45.16 45.17 gopts.opt('help', short='h', 45.18 fn=set_true, default=0, 45.19 @@ -24,18 +26,22 @@ gopts.opt('wait', short='w', 45.20 fn=set_true, default=0, 45.21 use='Wait for shutdown to complete.') 45.22 45.23 -gopts.opt('norestart', short='n', 45.24 +gopts.opt('halt', short='H', 45.25 fn=set_true, default=0, 45.26 - use='Prevent domain restart.') 45.27 + use='Shutdown without reboot.') 45.28 45.29 -def shutdown(opts, doms, wait): 45.30 +gopts.opt('reboot', short='R', 45.31 + fn=set_true, default=0, 45.32 + use='Shutdown and reboot.') 45.33 + 45.34 +def shutdown(opts, doms, mode, wait): 45.35 def domains(): 45.36 return [ int(a) for a in server.xend_domains() ] 45.37 if doms == None: doms = domains() 45.38 if 0 in doms: 45.39 doms.remove(0) 45.40 for d in doms: 45.41 - server.xend_domain_shutdown(d) 45.42 + server.xend_domain_shutdown(d, mode) 45.43 if wait: 45.44 while doms: 45.45 alive = domains() 45.46 @@ -49,6 +55,21 @@ def shutdown(opts, doms, wait): 45.47 time.sleep(1) 45.48 opts.info("All domains terminated") 45.49 45.50 +def shutdown_mode(opts): 45.51 + mode = 'poweroff' 45.52 + if opts.vals.wait: 45.53 + mode = 'halt' 45.54 + if opts.vals.reboot: 45.55 + opts.err("Can't specify wait and reboot") 45.56 + else: 45.57 + if opts.vals.halt and opts.vals.reboot: 45.58 + opts.err("Can't specify halt and reboot") 45.59 + if opts.vals.halt: 45.60 + mode = 'halt' 45.61 + elif opts.vals.reboot: 45.62 + mode = 'reboot' 45.63 + return mode 45.64 + 45.65 def main_all(opts, args): 45.66 shutdown(opts, None, opts.vals.wait) 45.67 45.68 @@ -59,7 +80,9 @@ def main_dom(opts, args): 45.69 domid = int(dom) 45.70 except: 45.71 opts.err('Invalid domain: ' + dom) 45.72 - shutdown(opts, [ domid ], opts.vals.wait) 45.73 + 45.74 + mode = shutdown_mode(opts) 45.75 + shutdown(opts, [ domid ], mode, opts.vals.wait) 45.76 45.77 def main(argv): 45.78 opts = gopts
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/tools/xfrd/Make.xfrd Tue Jul 06 17:27:27 2004 +0000 46.3 @@ -0,0 +1,34 @@ 46.4 +# -*- mode: Makefile; -*- 46.5 +#============================================================================ 46.6 + 46.7 +UTIL_LIB = libutil.a 46.8 + 46.9 +UTIL_LIB_SRC = 46.10 +UTIL_LIB_SRC += allocate.c 46.11 +UTIL_LIB_SRC += enum.c 46.12 +UTIL_LIB_SRC += file_stream.c 46.13 +UTIL_LIB_SRC += gzip_stream.c 46.14 +UTIL_LIB_SRC += hash_table.c 46.15 +UTIL_LIB_SRC += iostream.c 46.16 +UTIL_LIB_SRC += lexis.c 46.17 +UTIL_LIB_SRC += lzi_stream.c 46.18 +UTIL_LIB_SRC += marshal.c 46.19 +UTIL_LIB_SRC += string_stream.c 46.20 +UTIL_LIB_SRC += sxpr.c 46.21 +#UTIL_LIB_SRC += sxpr_parser.c 46.22 +UTIL_LIB_SRC += sys_net.c 46.23 +UTIL_LIB_SRC += sys_string.c 46.24 +#UTIL_LIB_SRC += util.c 46.25 +UTIL_LIB_SRC += xdr.c 46.26 + 46.27 +#---------------------------------------------------------------------------- 46.28 +# Xfrd. 46.29 + 46.30 +XFRD_PROG_SRC = 46.31 +XFRD_PROG_SRC += xfrd.c 46.32 +#XFRD_PROG_SRC += xfr_msg.c 46.33 +XFRD_PROG_SRC += xen_domain.c 46.34 +XFRD_PROG_SRC += select.c 46.35 +XFRD_PROG_SRC += connection.c 46.36 + 46.37 +#============================================================================
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/tools/xfrd/Makefile Tue Jul 06 17:27:27 2004 +0000 47.3 @@ -0,0 +1,68 @@ 47.4 +# -*- mode: Makefile; -*- 47.5 +#============================================================================ 47.6 +# 47.7 +# Mike Wray <mike.wray@hp.com> 47.8 +#============================================================================ 47.9 + 47.10 +XEN_ROOT = ../.. 47.11 +include $(XEN_ROOT)/tools/Make.defs 47.12 + 47.13 +XFRD_INSTALL_DIR = /usr/sbin 47.14 + 47.15 +vpath %.h $(XEN_HYPERVISOR_IFS) 47.16 +INCLUDES += -I $(XEN_HYPERVISOR_IFS) 47.17 + 47.18 +vpath %h $(XEN_LINUX_INCLUDE) 47.19 +INCLUDES += -I $(XEN_LINUX_INCLUDE) 47.20 + 47.21 +vpath %.h $(XEN_XU) 47.22 +INCLUDES += -I $(XEN_XU) 47.23 + 47.24 +vpath %c $(XEN_LIBXUTIL) 47.25 +INCLUDES += -I $(XEN_LIBXUTIL) 47.26 + 47.27 +include Make.xfrd 47.28 + 47.29 +UTIL_LIB_OBJ = $(UTIL_LIB_SRC:.c=.o) 47.30 + 47.31 +XFRD_PROG_OBJ = $(XFRD_PROG_SRC:.c=.o) 47.32 +XFRD_PROG_OBJ += $(UTIL_LIB) 47.33 + 47.34 +CPPFLAGS += -D _XEN_XFR_STUB_ 47.35 + 47.36 +CFLAGS += -g 47.37 +CFLAGS += -Wall 47.38 +CFALGS += -Werror 47.39 +CFLAGS += $(INCLUDES) 47.40 +# Make gcc generate dependencies. 47.41 +CFLAGS += -Wp,-MD,.$(@F).d 47.42 +PROG_DEP = .*.d 47.43 + 47.44 +#LDFLAGS += -L $(COMPRESS_DIR) -lz 47.45 + 47.46 +$(warning XFRD_PROG_OBJ= $(XFRD_PROG_OBJ)) 47.47 +$(warning UTIL_LIB= $(UTIL_LIB)) 47.48 +$(warning UTIL_LIB_OBJ= $(UTIL_LIB_OBJ)) 47.49 + 47.50 +all: xfrd 47.51 + 47.52 +xfrd: $(XFRD_PROG_OBJ) -lz 47.53 + 47.54 +.PHONY: install 47.55 +install: xfrd 47.56 + mkdir -p $(prefix)/$(XFRD_INSTALL_DIR) 47.57 + install -m 0755 xfrd $(prefix)/$(XFRD_INSTALL_DIR) 47.58 + 47.59 +.PHONY: libutil 47.60 +libutil: $(UTIL_LIB) 47.61 + 47.62 +$(UTIL_LIB): $(UTIL_LIB_OBJ) 47.63 + $(AR) rc $@ $^ 47.64 + 47.65 +.PHONY: clean 47.66 +clean: 47.67 + $(RM) *.o *.a *.so *~ xfrd 47.68 + $(RM) $(PROG_DEP) 47.69 + 47.70 +-include $(PROG_DEP) 47.71 +
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/tools/xfrd/connection.c Tue Jul 06 17:27:27 2004 +0000 48.3 @@ -0,0 +1,163 @@ 48.4 +#include <stdlib.h> 48.5 +#include <errno.h> 48.6 +#include <unistd.h> 48.7 +#include <sys/socket.h> 48.8 +#include <netinet/in.h> 48.9 +#include <arpa/inet.h> 48.10 + 48.11 +#include "connection.h" 48.12 +#include "file_stream.h" 48.13 +#include "lzi_stream.h" 48.14 + 48.15 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 48.16 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN] %s" fmt, __FUNCTION__, ##args) 48.17 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO] %s" fmt, __FUNCTION__, ##args) 48.18 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] %s" fmt, __FUNCTION__, ##args) 48.19 + 48.20 +/** Compress magic header. */ 48.21 +char compress_magic[2] = { 0x1f, 0x8b }; 48.22 + 48.23 +/** Plain magic header. */ 48.24 +char plain_magic[2] = { 0x0, 0x0 }; 48.25 + 48.26 +int Conn_read_header(int sock, int *flags){ 48.27 + int err = 0; 48.28 + char magic[2] = {}; 48.29 + int k, n = sizeof(magic); 48.30 + k = read(sock, magic, n); 48.31 + if(k != n){ 48.32 + err = -EINVAL; 48.33 + goto exit; 48.34 + } 48.35 + dprintf("> magic={ 0x%x, 0x%x }\n", magic[0], magic[1]); 48.36 + if(magic[0] == compress_magic[0] && magic[1] == compress_magic[1]){ 48.37 + *flags |= CONN_READ_COMPRESS; 48.38 + dprintf("> Using compress read.\n"); 48.39 + } else { 48.40 + dprintf("> Using plain read.\n"); 48.41 + } 48.42 + exit: 48.43 + return err; 48.44 +} 48.45 + 48.46 +int Conn_write_header(int sock, int flags){ 48.47 + int err = 0; 48.48 + if(flags & CONN_WRITE_COMPRESS){ 48.49 + dprintf("> Using compress write.\n"); 48.50 + err = write(sock, compress_magic, 2); 48.51 + } else { 48.52 + dprintf("> Using plain write.\n"); 48.53 + err = write(sock, plain_magic, 2); 48.54 + } 48.55 + if(err == 2) err = 0; 48.56 + return err; 48.57 +} 48.58 + 48.59 +/** Initialize a file stream from a file desciptor. 48.60 + * 48.61 + * @param fd file descriptor 48.62 + * @param mode file mode 48.63 + * @param flags control compression and buffering 48.64 + * @param io return parameter for the stream 48.65 + * @return 0 on success, error code otherwise 48.66 + */ 48.67 +int stream_init(int fd, const char *mode, int flags, int compress, IOStream **io){ 48.68 + int err = 0; 48.69 + dprintf(">mode=%s flags=%x compress=%d\n", mode, flags, compress); 48.70 + if(compress){ 48.71 + *io = lzi_stream_fdopen(fd, mode); 48.72 + } else { 48.73 + *io = file_stream_fdopen(fd, mode); 48.74 + } 48.75 + if(!*io){ 48.76 + err = -errno; 48.77 + perror("fdopen"); 48.78 + goto exit; 48.79 + } 48.80 + if(1 && (flags & CONN_NOBUFFER)){ 48.81 + // Make unbuffered. 48.82 + dprintf("> unbuffer...\n"); 48.83 + err = file_stream_setvbuf((compress ? lzi_stream_io(*io) : *io), NULL, _IONBF, 0); 48.84 + if(err){ 48.85 + err = -errno; 48.86 + perror("setvbuf"); 48.87 + goto exit; 48.88 + } 48.89 + } 48.90 + exit: 48.91 + if(err && *io){ 48.92 + dprintf("> close err=%d\n", err); 48.93 + IOStream_close(*io); 48.94 + *io = NULL; 48.95 + } 48.96 + dprintf("< err=%d\n", err); 48.97 + return err; 48.98 +} 48.99 + 48.100 +/** Initialize a connection. 48.101 + * 48.102 + * @param conn connection 48.103 + * @param flags 48.104 + * @param sock socket 48.105 + * @param ipaddr ip address 48.106 + * @return 0 on success, error code otherwise 48.107 + */ 48.108 +int Conn_init(Conn *conn, int flags, int sock, struct sockaddr_in addr){ 48.109 + int err = 0; 48.110 + dprintf("> flags=%x\n", flags); 48.111 + conn->addr = addr; 48.112 + conn->sock = sock; 48.113 + dprintf("> write stream...\n"); 48.114 + err = stream_init(sock, "w", flags, (flags & CONN_WRITE_COMPRESS), &conn->out); 48.115 + if(err) goto exit; 48.116 + IOStream_flush(conn->out); 48.117 + dprintf("> read stream...\n"); 48.118 + err = stream_init(sock, "r", flags, (flags & CONN_READ_COMPRESS) , &conn->in); 48.119 + if(err) goto exit; 48.120 + exit: 48.121 + if(err) eprintf("< err=%d\n", err); 48.122 + return err; 48.123 +} 48.124 + 48.125 +/** Open a connection. 48.126 + * 48.127 + * @param conn connection 48.128 + * @param flags 48.129 + * @param ipaddr ip address to connect to 48.130 + * @param port port 48.131 + * @return 0 on success, error code otherwise 48.132 + */ 48.133 +int Conn_connect(Conn *conn, int flags, struct in_addr ipaddr, uint16_t port){ 48.134 + int err = 0; 48.135 + int sock; 48.136 + struct sockaddr_in addr_in; 48.137 + struct sockaddr *addr = (struct sockaddr *)&addr_in; 48.138 + socklen_t addr_n = sizeof(addr_in); 48.139 + dprintf("> addr=%s:%d\n", inet_ntoa(ipaddr), ntohs(port)); 48.140 + sock = socket(AF_INET, SOCK_STREAM, 0); 48.141 + if(sock < 0){ 48.142 + err = -errno; 48.143 + goto exit; 48.144 + } 48.145 + addr_in.sin_family = AF_INET; 48.146 + addr_in.sin_addr = ipaddr; 48.147 + addr_in.sin_port = port; 48.148 + err = connect(sock, addr, addr_n); 48.149 + if(err) goto exit; 48.150 + //err = Conn_write_header(sock, flags); 48.151 + //if(err < 0) goto exit; 48.152 + err = Conn_init(conn, flags, sock, addr_in); 48.153 + exit: 48.154 + if(err) eprintf("< err=%d\n", err); 48.155 + return err; 48.156 +} 48.157 + 48.158 +/** Close a connection. 48.159 + * 48.160 + * @param conn connection 48.161 + */ 48.162 +void Conn_close(Conn *conn){ 48.163 + if(conn->in) IOStream_close(conn->in); 48.164 + if(conn->out) IOStream_close(conn->out); 48.165 + shutdown(conn->sock, 2); 48.166 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/tools/xfrd/connection.h Tue Jul 06 17:27:27 2004 +0000 49.3 @@ -0,0 +1,32 @@ 49.4 +/* $Id: connection.h,v 1.1 2003/10/17 15:48:43 mjw Exp $ */ 49.5 +#ifndef _VFC_CONNECTION_H_ 49.6 +#define _VFC_CONNECTION_H_ 49.7 + 49.8 +#include <netinet/in.h> 49.9 + 49.10 +#include "iostream.h" 49.11 + 49.12 +/** A connection. 49.13 + * The underlying transport is a socket. 49.14 + * Contains in and out streams using the socket. 49.15 + */ 49.16 +typedef struct Conn { 49.17 + struct sockaddr_in addr; 49.18 + int sock; 49.19 + IOStream *in; 49.20 + IOStream *out; 49.21 +} Conn; 49.22 + 49.23 +enum { 49.24 + CONN_NOBUFFER=1, 49.25 + CONN_READ_COMPRESS=2, 49.26 + CONN_WRITE_COMPRESS=4, 49.27 +}; 49.28 + 49.29 +extern int Conn_read_header(int sock, int *flags); 49.30 +extern int Conn_write_header(int sock, int flags); 49.31 +extern int Conn_init(Conn *conn, int flags, int sock, struct sockaddr_in addr); 49.32 +extern int Conn_connect(Conn *conn, int flags, struct in_addr ipaddr, uint16_t port); 49.33 +extern void Conn_close(Conn *conn); 49.34 + 49.35 +#endif /* ! _VFC_CONNECTION_H_ */
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/tools/xfrd/debug.h Tue Jul 06 17:27:27 2004 +0000 50.3 @@ -0,0 +1,72 @@ 50.4 +/* 50.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 50.6 + * 50.7 + * This library is free software; you can redistribute it and/or modify 50.8 + * it under the terms of the GNU Lesser General Public License as published by 50.9 + * the Free Software Foundation; either version 2.1 of the License, or 50.10 + * (at your option) any later version. 50.11 + * 50.12 + * This library is distributed in the hope that it will be useful, 50.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 50.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 50.15 + * GNU Lesser General Public License for more details. 50.16 + * 50.17 + * You should have received a copy of the GNU Lesser General Public License 50.18 + * along with this library; if not, write to the Free Software 50.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 50.20 + */ 50.21 +#ifndef _XUTIL_DEBUG_H_ 50.22 +#define _XUTIL_DEBUG_H_ 50.23 + 50.24 +#ifndef MODULE_NAME 50.25 +#define MODULE_NAME "" 50.26 +#endif 50.27 + 50.28 +#ifdef __KERNEL__ 50.29 +#include <linux/config.h> 50.30 +#include <linux/kernel.h> 50.31 + 50.32 +#ifdef DEBUG 50.33 + 50.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.36 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.37 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.38 + 50.39 +#else 50.40 + 50.41 +#define dprintf(fmt, args...) do {} while(0) 50.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args) 50.43 +#define iprintf(fmt, args...) printk(KERN_INFO "[INF] " MODULE_NAME fmt, ##args) 50.44 +#define eprintf(fmt, args...) printk(KERN_ERR "[ERR] " MODULE_NAME fmt, ##args) 50.45 + 50.46 +#endif 50.47 + 50.48 +#else 50.49 + 50.50 +#include <stdio.h> 50.51 + 50.52 +#ifdef DEBUG 50.53 + 50.54 +#define dprintf(fmt, args...) fprintf(stdout, "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.55 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.56 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.57 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args) 50.58 + 50.59 +#else 50.60 + 50.61 +#define dprintf(fmt, args...) do {} while(0) 50.62 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME fmt, ##args) 50.63 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME fmt, ##args) 50.64 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME fmt, ##args) 50.65 + 50.66 +#endif 50.67 + 50.68 +#endif 50.69 + 50.70 +/** Print format for an IP address. 50.71 + * See NIPQUAD(), HIPQUAD() 50.72 + */ 50.73 +#define IPFMT "%u.%u.%u.%u" 50.74 + 50.75 +#endif /* ! _XUTIL_DEBUG_H_ */
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/tools/xfrd/enum.c Tue Jul 06 17:27:27 2004 +0000 51.3 @@ -0,0 +1,61 @@ 51.4 +/* 51.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com> 51.6 + * 51.7 + * This library is free software; you can redistribute it and/or modify 51.8 + * it under the terms of the GNU Lesser General Public License as 51.9 + * published by the Free Software Foundation; either version 2.1 of the 51.10 + * License, or (at your option) any later version. This library is 51.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 51.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 51.13 + * FITNESS FOR A PARTICULAR PURPOSE. 51.14 + * See the GNU Lesser General Public License for more details. 51.15 + * 51.16 + * You should have received a copy of the GNU Lesser General Public License 51.17 + * along with this library; if not, write to the Free Software Foundation, 51.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 51.19 + */ 51.20 + 51.21 +#ifdef __KERNEL__ 51.22 +#include <linux/errno.h> 51.23 +#else 51.24 +#include <errno.h> 51.25 +#endif 51.26 + 51.27 +#include "sys_string.h" 51.28 +#include "enum.h" 51.29 + 51.30 +/** Map an enum name to its value using a table. 51.31 + * 51.32 + * @param name enum name 51.33 + * @param defs enum definitions 51.34 + * @return enum value or -1 if not known 51.35 + */ 51.36 +int enum_name_to_val(char *name, EnumDef *defs){ 51.37 + int val = -1; 51.38 + for(; defs->name; defs++){ 51.39 + if(!strcmp(defs->name, name)){ 51.40 + val = defs->val; 51.41 + break; 51.42 + } 51.43 + } 51.44 + return val; 51.45 +} 51.46 + 51.47 +/** Map an enum value to its name using a table. 51.48 + * 51.49 + * @param val enum value 51.50 + * @param defs enum definitions 51.51 + * @param defs_n number of definitions 51.52 + * @return enum name or NULL if not known 51.53 + */ 51.54 +char *enum_val_to_name(int val, EnumDef *defs){ 51.55 + char *name = NULL; 51.56 + for(; defs->name; defs++){ 51.57 + if(val == defs->val){ 51.58 + name = defs->name; 51.59 + break; 51.60 + } 51.61 + } 51.62 + return name; 51.63 +} 51.64 +
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/tools/xfrd/enum.h Tue Jul 06 17:27:27 2004 +0000 52.3 @@ -0,0 +1,30 @@ 52.4 +/* 52.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com> 52.6 + * 52.7 + * This library is free software; you can redistribute it and/or modify 52.8 + * it under the terms of the GNU Lesser General Public License as 52.9 + * published by the Free Software Foundation; either version 2.1 of the 52.10 + * License, or (at your option) any later version. This library is 52.11 + * distributed in the hope that it will be useful, but WITHOUT ANY 52.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 52.13 + * FITNESS FOR A PARTICULAR PURPOSE. 52.14 + * See the GNU Lesser General Public License for more details. 52.15 + * 52.16 + * You should have received a copy of the GNU Lesser General Public License 52.17 + * along with this library; if not, write to the Free Software Foundation, 52.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 52.19 + */ 52.20 + 52.21 +#ifndef _XUTIL_ENUM_H_ 52.22 +#define _XUTIL_ENUM_H_ 52.23 + 52.24 +/** Mapping of an enum value to a name. */ 52.25 +typedef struct EnumDef { 52.26 + int val; 52.27 + char *name; 52.28 +} EnumDef; 52.29 + 52.30 +extern int enum_name_to_val(char *name, EnumDef *defs); 52.31 +extern char *enum_val_to_name(int val, EnumDef *defs); 52.32 + 52.33 +#endif /* _XUTIL_ENUM_H_ */
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/tools/xfrd/hash_table.c Tue Jul 06 17:27:27 2004 +0000 53.3 @@ -0,0 +1,640 @@ 53.4 +/* 53.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 53.6 + * 53.7 + * This library is free software; you can redistribute it and/or modify 53.8 + * it under the terms of the GNU Lesser General Public License as published by 53.9 + * the Free Software Foundation; either version 2.1 of the License, or 53.10 + * (at your option) any later version. 53.11 + * 53.12 + * This library is distributed in the hope that it will be useful, 53.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 53.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 53.15 + * GNU Lesser General Public License for more details. 53.16 + * 53.17 + * You should have received a copy of the GNU Lesser General Public License 53.18 + * along with this library; if not, write to the Free Software 53.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 53.20 + */ 53.21 + 53.22 +#ifdef __KERNEL__ 53.23 +# include <linux/config.h> 53.24 +# include <linux/module.h> 53.25 +# include <linux/kernel.h> 53.26 +# include <linux/errno.h> 53.27 +#else 53.28 +# include <errno.h> 53.29 +# include <stddef.h> 53.30 +#endif 53.31 + 53.32 +//#include <limits.h> 53.33 + 53.34 +#include "allocate.h" 53.35 +#include "hash_table.h" 53.36 + 53.37 +/** @file 53.38 + * Base support for hashtables. 53.39 + * 53.40 + * Hash codes are reduced modulo the number of buckets to index tables, 53.41 + * so there is no need for hash functions to limit the range of hashcodes. 53.42 + * In fact it is assumed that hashcodes do not change when the number of 53.43 + * buckets in the table changes. 53.44 + */ 53.45 + 53.46 +/*==========================================================================*/ 53.47 +/** Number of bits in half a word. */ 53.48 +//#if __WORDSIZE == 64 53.49 +//#define HALF_WORD_BITS 32 53.50 +//#else 53.51 +#define HALF_WORD_BITS 16 53.52 +//#endif 53.53 + 53.54 +/** Mask for lo half of a word. On 32-bit this is 53.55 + * (1<<16) - 1 = 65535 = 0xffff 53.56 + * It's 4294967295 = 0xffffffff on 64-bit. 53.57 + */ 53.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1) 53.59 + 53.60 +/** Get the lo half of a word. */ 53.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK) 53.62 + 53.63 +/** Get the hi half of a word. */ 53.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS) 53.65 + 53.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling. 53.67 + * Both inputs are replaced with the results of the hash. 53.68 + * 53.69 + * @param pleft input/output word 53.70 + * @param pright input/output word 53.71 + */ 53.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){ 53.73 + // Bit-rich mixing constant. 53.74 + static const unsigned long a_mixer[] = { 53.75 + 0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, }; 53.76 + 53.77 + // Bit-rich mixing constant. 53.78 + static const unsigned long b_mixer[] = { 53.79 + 0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, }; 53.80 + 53.81 + // Number of iterations - must be 2 or 4. 53.82 + static const int ncycle = 4; 53.83 + //static const int ncycle = 2; 53.84 + 53.85 + unsigned long left = *pleft, right = *pright; 53.86 + unsigned long v, v_hi, v_lo; 53.87 + int i; 53.88 + 53.89 + for(i=0; i<ncycle; i++){ 53.90 + // Flip some bits in right to get v. 53.91 + v = right; 53.92 + v ^= a_mixer[i]; 53.93 + // Get lo and hi halves of v. 53.94 + v_lo = LO_HALF(v); 53.95 + v_hi = HI_HALF(v); 53.96 + // Non-linear mix of the halves of v. 53.97 + v = ((v_lo * v_lo) + ~(v_hi * v_hi)); 53.98 + // Swap the halves of v. 53.99 + v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS)); 53.100 + // Flip some bits. 53.101 + v ^= b_mixer[i]; 53.102 + // More non-linear mixing. 53.103 + v += (v_lo * v_hi); 53.104 + v ^= left; 53.105 + left = right; 53.106 + right = v; 53.107 + } 53.108 + *pleft = left; 53.109 + *pright = right; 53.110 +} 53.111 + 53.112 +/** Hash a string. 53.113 + * 53.114 + * @param s input to hash 53.115 + * @return hashcode 53.116 + */ 53.117 +Hashcode hash_string(char *s){ 53.118 + Hashcode h = 0; 53.119 + if(s){ 53.120 + for( ; *s; s++){ 53.121 + h = hash_2ul(h, *s); 53.122 + } 53.123 + } 53.124 + return h; 53.125 +} 53.126 + 53.127 +/** Get the bucket for a hashcode in a hash table. 53.128 + * 53.129 + * @param table to get bucket from 53.130 + * @param hashcode to get bucket for 53.131 + * @return bucket 53.132 + */ 53.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){ 53.134 + return table->buckets + (hashcode % table->buckets_n); 53.135 +} 53.136 + 53.137 +/** Initialize a hash table. 53.138 + * Can be safely called more than once. 53.139 + * 53.140 + * @param table to initialize 53.141 + */ 53.142 +void HashTable_init(HashTable *table){ 53.143 + int i; 53.144 + 53.145 + if(!table->init_done){ 53.146 + table->init_done = 1; 53.147 + table->next_id = 0; 53.148 + for(i=0; i<table->buckets_n; i++){ 53.149 + HTBucket *bucket = get_bucket(table, i); 53.150 + bucket->head = 0; 53.151 + bucket->count = 0; 53.152 + } 53.153 + table->entry_count = 0; 53.154 + } 53.155 +} 53.156 + 53.157 +/** Allocate a new hashtable. 53.158 + * If the number of buckets is not positive the default is used. 53.159 + * The number of buckets should usually be prime. 53.160 + * 53.161 + * @param buckets_n number of buckets 53.162 + * @return new hashtable or null 53.163 + */ 53.164 +HashTable *HashTable_new(int buckets_n){ 53.165 + HashTable *z = ALLOCATE(HashTable); 53.166 + if(!z) goto exit; 53.167 + if(buckets_n <= 0){ 53.168 + buckets_n = HT_BUCKETS_N; 53.169 + } 53.170 + z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 53.171 + if(!z->buckets){ 53.172 + deallocate(z); 53.173 + z = 0; 53.174 + goto exit; 53.175 + } 53.176 + z->buckets_n = buckets_n; 53.177 + HashTable_init(z); 53.178 + exit: 53.179 + return z; 53.180 +} 53.181 + 53.182 +/** Free a hashtable. 53.183 + * Any entries are removed and freed. 53.184 + * 53.185 + * @param h hashtable (ignored if null) 53.186 + */ 53.187 +void HashTable_free(HashTable *h){ 53.188 + if(h){ 53.189 + HashTable_clear(h); 53.190 + deallocate(h->buckets); 53.191 + deallocate(h); 53.192 + } 53.193 +} 53.194 + 53.195 +/** Push an entry on the list in the bucket for a given hashcode. 53.196 + * 53.197 + * @param table to add entry to 53.198 + * @param hashcode for the entry 53.199 + * @param entry to add 53.200 + */ 53.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode, 53.202 + HTEntry *entry){ 53.203 + HTBucket *bucket; 53.204 + HTEntry *old_head; 53.205 + 53.206 + bucket = get_bucket(table, hashcode); 53.207 + old_head = bucket->head; 53.208 + bucket->count++; 53.209 + bucket->head = entry; 53.210 + entry->next = old_head; 53.211 +} 53.212 + 53.213 +/** Change the number of buckets in a hashtable. 53.214 + * No-op if the number of buckets is not positive. 53.215 + * Existing entries are reallocated to buckets based on their hashcodes. 53.216 + * The table is unmodified if the number of buckets cannot be changed. 53.217 + * 53.218 + * @param table hashtable 53.219 + * @param buckets_n new number of buckets 53.220 + * @return 0 on success, error code otherwise 53.221 + */ 53.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){ 53.223 + int err = 0; 53.224 + HTBucket *old_buckets = table->buckets; 53.225 + int old_buckets_n = table->buckets_n; 53.226 + int i; 53.227 + 53.228 + if(buckets_n <= 0){ 53.229 + err = -EINVAL; 53.230 + goto exit; 53.231 + } 53.232 + table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket)); 53.233 + if(!table->buckets){ 53.234 + err = -ENOMEM; 53.235 + table->buckets = old_buckets; 53.236 + goto exit; 53.237 + } 53.238 + table->buckets_n = buckets_n; 53.239 + for(i=0; i<old_buckets_n; i++){ 53.240 + HTBucket *bucket = old_buckets + i; 53.241 + HTEntry *entry, *next; 53.242 + for(entry = bucket->head; entry; entry = next){ 53.243 + next = entry->next; 53.244 + push_on_bucket(table, entry->hashcode, entry); 53.245 + } 53.246 + } 53.247 + deallocate(old_buckets); 53.248 + exit: 53.249 + return err; 53.250 +} 53.251 + 53.252 +/** Adjust the number of buckets so the table is neither too full nor too empty. 53.253 + * The table is unmodified if adjusting fails. 53.254 + * 53.255 + * @param table hash table 53.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative) 53.257 + * @return 0 on success, error code otherwise 53.258 + */ 53.259 +int HashTable_adjust(HashTable *table, int buckets_min){ 53.260 + int buckets_n = 0; 53.261 + int err = 0; 53.262 + if(buckets_min <= 0) buckets_min = HT_BUCKETS_N; 53.263 + if(table->entry_count >= table->buckets_n){ 53.264 + // The table is dense - expand it. 53.265 + buckets_n = 2 * table->buckets_n; 53.266 + } else if((table->buckets_n > buckets_min) && 53.267 + (4 * table->entry_count < table->buckets_n)){ 53.268 + // The table is more than minimum size and sparse - shrink it. 53.269 + buckets_n = 2 * table->entry_count; 53.270 + if(buckets_n < buckets_min) buckets_n = buckets_min; 53.271 + } 53.272 + if(buckets_n){ 53.273 + err = HashTable_set_buckets_n(table, buckets_n); 53.274 + } 53.275 + return err; 53.276 +} 53.277 + 53.278 +/** Allocate a new entry for a given value. 53.279 + * 53.280 + * @param value to put in the entry 53.281 + * @return entry, or 0 on failure 53.282 + */ 53.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){ 53.284 + HTEntry *z = ALLOCATE(HTEntry); 53.285 + if(z){ 53.286 + z->hashcode = hashcode; 53.287 + z->key = key; 53.288 + z->value = value; 53.289 + } 53.290 + return z; 53.291 +} 53.292 + 53.293 +/** Free an entry. 53.294 + * 53.295 + * @param z entry to free 53.296 + */ 53.297 +inline void HTEntry_free(HTEntry *z){ 53.298 + if(z){ 53.299 + deallocate(z); 53.300 + } 53.301 +} 53.302 + 53.303 +/** Free an entry in a hashtable. 53.304 + * The table's entry_free_fn is used is defined, otherwise 53.305 + * the HTEntry itself is freed. 53.306 + * 53.307 + * @param table hashtable 53.308 + * @param entry to free 53.309 + */ 53.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){ 53.311 + if(!entry)return; 53.312 + if(table && table->entry_free_fn){ 53.313 + table->entry_free_fn(table, entry); 53.314 + } else { 53.315 + HTEntry_free(entry); 53.316 + } 53.317 +} 53.318 + 53.319 +/** Get the first entry satisfying a test from the bucket for the 53.320 + * given hashcode. 53.321 + * 53.322 + * @param table to look in 53.323 + * @param hashcode indicates the bucket 53.324 + * @param test_fn test to apply to elements 53.325 + * @param arg first argument to calls to test_fn 53.326 + * @return entry found, or 0 53.327 + */ 53.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 53.329 + TableTestFn *test_fn, TableArg arg){ 53.330 + HTBucket *bucket; 53.331 + HTEntry *entry = 0; 53.332 + HTEntry *next; 53.333 + 53.334 + bucket = get_bucket(table, hashcode); 53.335 + for(entry = bucket->head; entry; entry = next){ 53.336 + next = entry->next; 53.337 + if(test_fn(arg, table, entry)){ 53.338 + break; 53.339 + } 53.340 + } 53.341 + return entry; 53.342 +} 53.343 + 53.344 +/** Test hashtable keys for equality. 53.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality. 53.346 + * 53.347 + * @param key1 key to compare 53.348 + * @param key2 key to compare 53.349 + * @return 1 if equal, 0 otherwise 53.350 + */ 53.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){ 53.352 + return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2); 53.353 +} 53.354 + 53.355 +/** Compute the hashcode of a hashtable key. 53.356 + * The table's key_hash_fn is used if defined, otherwise the address of 53.357 + * the key is hashed. 53.358 + * 53.359 + * @param table hashtable 53.360 + * @param key to hash 53.361 + * @return hashcode 53.362 + */ 53.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){ 53.364 + return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key)); 53.365 +} 53.366 + 53.367 +/** Test if an entry has a given key. 53.368 + * 53.369 + * @param arg containing key to test for 53.370 + * @param table the entry is in 53.371 + * @param entry to test 53.372 + * @return 1 if the entry has the key, 0 otherwise 53.373 + */ 53.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){ 53.375 + return HashTable_key_equal(table, arg.ptr, entry->key); 53.376 +} 53.377 + 53.378 +/** Get an entry with a given key. 53.379 + * 53.380 + * @param table to search 53.381 + * @param key to look for 53.382 + * @return entry if found, null otherwise 53.383 + */ 53.384 +#if 0 53.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 53.386 + TableArg arg = { ptr: key }; 53.387 + return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg); 53.388 +} 53.389 +#else 53.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){ 53.391 + Hashcode hashcode; 53.392 + HTBucket *bucket; 53.393 + HTEntry *entry = 0; 53.394 + HTEntry *next; 53.395 + 53.396 + hashcode = HashTable_key_hash(table, key); 53.397 + bucket = get_bucket(table, hashcode); 53.398 + for(entry = bucket->head; entry; entry = next){ 53.399 + next = entry->next; 53.400 + if(HashTable_key_equal(table, key, entry->key)){ 53.401 + break; 53.402 + } 53.403 + } 53.404 + return entry; 53.405 +} 53.406 +#endif 53.407 + 53.408 +/** Get the value of an entry with a given key. 53.409 + * 53.410 + * @param table to search 53.411 + * @param key to look for 53.412 + * @return value if an entry was found, null otherwise 53.413 + */ 53.414 +inline void * HashTable_get(HashTable *table, void *key){ 53.415 + HTEntry *entry = HashTable_get_entry(table, key); 53.416 + return (entry ? entry->value : 0); 53.417 +} 53.418 + 53.419 +/** Print the buckets in a table. 53.420 + * 53.421 + * @param table to print 53.422 + */ 53.423 +void show_buckets(HashTable *table, IOStream *io){ 53.424 + int i,j ; 53.425 + IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n); 53.426 + for(i=0; i<table->buckets_n; i++){ 53.427 + if(0 || table->buckets[i].count>0){ 53.428 + IOStream_print(io, "bucket %3d %3d %10p ", i, 53.429 + table->buckets[i].count, 53.430 + table->buckets[i].head); 53.431 + for(j = table->buckets[i].count; j>0; j--){ 53.432 + IOStream_print(io, "+"); 53.433 + } 53.434 + IOStream_print(io, "\n"); 53.435 + } 53.436 + } 53.437 + HashTable_print(table, io); 53.438 +} 53.439 + 53.440 +/** Print an entry in a table. 53.441 + * 53.442 + * @param entry to print 53.443 + * @param arg a pointer to an IOStream to print to 53.444 + * @return 0 53.445 + */ 53.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){ 53.447 + IOStream *io = (IOStream*)arg.ptr; 53.448 + IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n", 53.449 + entry->hashcode % table->buckets_n, 53.450 + entry->hashcode, 53.451 + entry->index, 53.452 + entry, entry->key, entry->value); 53.453 + return 0; 53.454 +} 53.455 + 53.456 +/** Print a hash table. 53.457 + * 53.458 + * @param table to print 53.459 + */ 53.460 +void HashTable_print(HashTable *table, IOStream *io){ 53.461 + IOStream_print(io, "{\n"); 53.462 + HashTable_map(table, print_entry, (TableArg){ ptr: io }); 53.463 + IOStream_print(io, "}\n"); 53.464 +} 53.465 +/*==========================================================================*/ 53.466 + 53.467 +/** Get the next entry id to use for a table. 53.468 + * 53.469 + * @param table hash table 53.470 + * @return non-zero entry id 53.471 + */ 53.472 +static inline unsigned long get_next_id(HashTable *table){ 53.473 + unsigned long id; 53.474 + 53.475 + if(table->next_id == 0){ 53.476 + table->next_id = 1; 53.477 + } 53.478 + id = table->next_id++; 53.479 + return id; 53.480 +} 53.481 + 53.482 +/** Add an entry to the bucket for the 53.483 + * given hashcode. 53.484 + * 53.485 + * @param table to insert in 53.486 + * @param hashcode indicates the bucket 53.487 + * @param key to add an entry for 53.488 + * @param value to add an entry for 53.489 + * @return entry on success, 0 on failure 53.490 + */ 53.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){ 53.492 + HTEntry *entry = HTEntry_new(hashcode, key, value); 53.493 + if(entry){ 53.494 + entry->index = get_next_id(table); 53.495 + push_on_bucket(table, hashcode, entry); 53.496 + table->entry_count++; 53.497 + } 53.498 + return entry; 53.499 +} 53.500 + 53.501 +/** Move the front entry for a bucket to the correct point in the bucket order as 53.502 + * defined by the order function. If this is called every time a new entry is added 53.503 + * the bucket will be maintained in sorted order. 53.504 + * 53.505 + * @param table to modify 53.506 + * @param hashcode indicates the bucket 53.507 + * @param order entry comparison function 53.508 + * @return 0 if an entry was moved, 1 if not 53.509 + */ 53.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){ 53.511 + HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL; 53.512 + HTBucket *bucket; 53.513 + int err = 1; 53.514 + 53.515 + bucket = get_bucket(table, hashcode); 53.516 + new_entry = bucket->head; 53.517 + if(!new_entry || !new_entry->next) goto exit; 53.518 + for(entry = new_entry->next; entry; prev = entry, entry = entry->next){ 53.519 + if(order(new_entry, entry) <= 0) break; 53.520 + } 53.521 + if(prev){ 53.522 + err = 0; 53.523 + bucket->head = new_entry->next; 53.524 + new_entry->next = entry; 53.525 + prev->next = new_entry; 53.526 + } 53.527 + exit: 53.528 + return err; 53.529 +} 53.530 + 53.531 +/** Add an entry to a hashtable. 53.532 + * The entry is added to the bucket for its key's hashcode. 53.533 + * 53.534 + * @param table to insert in 53.535 + * @param key to add an entry for 53.536 + * @param value to add an entry for 53.537 + * @return entry on success, 0 on failure 53.538 + */ 53.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){ 53.540 + return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value); 53.541 +} 53.542 + 53.543 + 53.544 +/** Remove entries satisfying a test from the bucket for the 53.545 + * given hashcode. 53.546 + * 53.547 + * @param table to remove from 53.548 + * @param hashcode indicates the bucket 53.549 + * @param test_fn test to apply to elements 53.550 + * @param arg first argument to calls to test_fn 53.551 + * @return number of entries removed 53.552 + */ 53.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 53.554 + TableTestFn *test_fn, TableArg arg){ 53.555 + HTBucket *bucket; 53.556 + HTEntry *entry, *prev = 0, *next; 53.557 + int removed_count = 0; 53.558 + 53.559 + bucket = get_bucket(table, hashcode); 53.560 + for(entry = bucket->head; entry; entry = next){ 53.561 + next = entry->next; 53.562 + if(test_fn(arg, table, entry)){ 53.563 + if(prev){ 53.564 + prev->next = next; 53.565 + } else { 53.566 + bucket->head = next; 53.567 + } 53.568 + bucket->count--; 53.569 + table->entry_count--; 53.570 + removed_count++; 53.571 + HashTable_free_entry(table, entry); 53.572 + entry = 0; 53.573 + } 53.574 + prev = entry; 53.575 + } 53.576 + return removed_count; 53.577 +} 53.578 + 53.579 +/** Remove entries with a given key. 53.580 + * 53.581 + * @param table to remove from 53.582 + * @param key of entries to remove 53.583 + * @return number of entries removed 53.584 + */ 53.585 +inline int HashTable_remove(HashTable *table, void *key){ 53.586 +#if 1 53.587 + Hashcode hashcode; 53.588 + HTBucket *bucket; 53.589 + HTEntry *entry, *prev = 0, *next; 53.590 + int removed_count = 0; 53.591 + 53.592 + hashcode = HashTable_key_hash(table, key); 53.593 + bucket = get_bucket(table, hashcode); 53.594 + for(entry = bucket->head; entry; entry = next){ 53.595 + next = entry->next; 53.596 + if(HashTable_key_equal(table, key, entry->key)){ 53.597 + if(prev){ 53.598 + prev->next = next; 53.599 + } else { 53.600 + bucket->head = next; 53.601 + } 53.602 + bucket->count--; 53.603 + table->entry_count--; 53.604 + removed_count++; 53.605 + HashTable_free_entry(table, entry); 53.606 + entry = 0; 53.607 + } 53.608 + prev = entry; 53.609 + } 53.610 + return removed_count; 53.611 +#else 53.612 + return HashTable_remove_entry(table, HashTable_key_hash(table, key), 53.613 + has_key, (TableArg){ ptr: key}); 53.614 +#endif 53.615 +} 53.616 + 53.617 +/** Remove (and free) all the entries in a bucket. 53.618 + * 53.619 + * @param bucket to clear 53.620 + */ 53.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){ 53.622 + HTEntry *entry, *next; 53.623 + 53.624 + for(entry = bucket->head; entry; entry = next){ 53.625 + next = entry->next; 53.626 + HashTable_free_entry(table, entry); 53.627 + } 53.628 + bucket->head = 0; 53.629 + table->entry_count -= bucket->count; 53.630 + bucket->count = 0; 53.631 +} 53.632 + 53.633 +/** Remove (and free) all the entries in a table. 53.634 + * 53.635 + * @param table to clear 53.636 + */ 53.637 +void HashTable_clear(HashTable *table){ 53.638 + int i, n = table->buckets_n; 53.639 + 53.640 + for(i=0; i<n; i++){ 53.641 + bucket_clear(table, table->buckets + i); 53.642 + } 53.643 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/tools/xfrd/hash_table.h Tue Jul 06 17:27:27 2004 +0000 54.3 @@ -0,0 +1,294 @@ 54.4 +/* 54.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com> 54.6 + * 54.7 + * This library is free software; you can redistribute it and/or modify 54.8 + * it under the terms of the GNU Lesser General Public License as published by 54.9 + * the Free Software Foundation; either version 2.1 of the License, or 54.10 + * (at your option) any later version. 54.11 + * 54.12 + * This library is distributed in the hope that it will be useful, 54.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 54.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 54.15 + * GNU Lesser General Public License for more details. 54.16 + * 54.17 + * You should have received a copy of the GNU Lesser General Public License 54.18 + * along with this library; if not, write to the Free Software 54.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 54.20 + */ 54.21 + 54.22 +#ifndef _XUTIL_HASH_TABLE_H_ 54.23 +#define _XUTIL_HASH_TABLE_H_ 54.24 + 54.25 +#include "iostream.h" 54.26 + 54.27 +typedef unsigned long Hashcode; 54.28 + 54.29 +/** Type used to pass parameters to table functions. */ 54.30 +typedef union TableArg { 54.31 + unsigned long ul; 54.32 + void *ptr; 54.33 +} TableArg; 54.34 + 54.35 +/** An entry in a bucket list. */ 54.36 +typedef struct HTEntry { 54.37 + /** Hashcode of the entry's key. */ 54.38 + Hashcode hashcode; 54.39 + /** Identifier for this entry in the table. */ 54.40 + int index; 54.41 + /** The key for this entry. */ 54.42 + void *key; 54.43 + /** The value in this entry. */ 54.44 + void *value; 54.45 + /** The next entry in the list. */ 54.46 + struct HTEntry *next; 54.47 +} HTEntry; 54.48 + 54.49 +/** A bucket in a rule table. */ 54.50 +typedef struct HTBucket { 54.51 + /** Number of entries in the bucket. */ 54.52 + int count; 54.53 + /** First entry in the bucket (may be null). */ 54.54 + HTEntry *head; 54.55 +} HTBucket; 54.56 + 54.57 +/** Default number of buckets in a hash table. 54.58 + * You want enough buckets so the lists in the buckets will typically be short. 54.59 + * It's a good idea if this is prime, since that will help to spread hashcodes 54.60 + * around the table. 54.61 + */ 54.62 +//#define HT_BUCKETS_N 1 54.63 +//#define HT_BUCKETS_N 3 54.64 +//#define HT_BUCKETS_N 7 54.65 +//#define HT_BUCKETS_N 17 54.66 +//#define HT_BUCKETS_N 97 54.67 +//#define HT_BUCKETS_N 211 54.68 +//#define HT_BUCKETS_N 401 54.69 +#define HT_BUCKETS_N 1021 54.70 + 54.71 +typedef struct HashTable HashTable; 54.72 + 54.73 +/** Type for a function used to select table entries. */ 54.74 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry); 54.75 + 54.76 +/** Type for a function to map over table entries. */ 54.77 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry); 54.78 + 54.79 +/** Type for a function to free table entries. */ 54.80 +typedef void TableFreeFn(HashTable *table, HTEntry *entry); 54.81 + 54.82 +/** Type for a function to hash table keys. */ 54.83 +typedef Hashcode TableHashFn(void *key); 54.84 + 54.85 +/** Type for a function to test table keys for equality. */ 54.86 +typedef int TableEqualFn(void *key1, void *key2); 54.87 + 54.88 +/** Type for a function to order table entries. */ 54.89 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2); 54.90 + 54.91 +/** General hash table. 54.92 + * A hash table with a list in each bucket. 54.93 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys. 54.94 + * These all default to 0, when default behaviour treating keys as integers is used. 54.95 + */ 54.96 +struct HashTable { 54.97 + /** Flag indicating whether the table has been initialised. */ 54.98 + int init_done; 54.99 + /** Next value for the id field in inserted rules. */ 54.100 + unsigned long next_id; 54.101 + /** Number of buckets in the bucket array. */ 54.102 + int buckets_n; 54.103 + /** Array of buckets, each with its own list. */ 54.104 + HTBucket *buckets; 54.105 + /** Number of entries in the table. */ 54.106 + int entry_count; 54.107 + /** Function to free keys and values in entries. */ 54.108 + TableFreeFn *entry_free_fn; 54.109 + /** Function to hash keys. */ 54.110 + TableHashFn *key_hash_fn; 54.111 + /** Function to compare keys for equality. */ 54.112 + TableEqualFn *key_equal_fn; 54.113 + /** Place for the user of the table to hang extra data. */ 54.114 + void *user_data; 54.115 +}; 54.116 + 54.117 +extern HashTable *HashTable_new(int bucket_n); 54.118 +extern void HashTable_free(HashTable *table); 54.119 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value); 54.120 +extern void HTEntry_free(HTEntry *entry); 54.121 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n); 54.122 +extern void HashTable_clear(HashTable *table); 54.123 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value); 54.124 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key); 54.125 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value); 54.126 +extern void * HashTable_get(HashTable *table, void *key); 54.127 +extern int HashTable_remove(HashTable *table, void *key); 54.128 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode, 54.129 + TableTestFn *test_fn, TableArg arg); 54.130 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode, 54.131 + TableTestFn *test_fn, TableArg arg); 54.132 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg); 54.133 +extern void HashTable_print(HashTable *table, IOStream *out); 54.134 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n); 54.135 +extern int HashTable_adjust(HashTable *table, int buckets_min); 54.136 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright); 54.137 +extern Hashcode hash_string(char *s); 54.138 + 54.139 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order); 54.140 + 54.141 +/** Control whether to use hashing based on DES or simple 54.142 + * hashing. DES hashing is `more random' but much more expensive. 54.143 + */ 54.144 +#define HASH_PSEUDO_DES 0 54.145 + 54.146 +/** Hash a long using a quick and dirty linear congruential random number generator. 54.147 + * See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator". 54.148 + * 54.149 + * @param a value to hash 54.150 + * @return hashed input 54.151 + */ 54.152 +static inline unsigned long lcrng_hash(unsigned long a){ 54.153 + return (1664525L * a + 1013904223L); 54.154 +} 54.155 + 54.156 +/** Hash an unsigned long. 54.157 + * 54.158 + * @param a input to hash 54.159 + * @return hashcode 54.160 + */ 54.161 +static inline Hashcode hash_ul(unsigned long a){ 54.162 +#if HASH_PSEUDO_DES 54.163 + unsigned long left = a; 54.164 + unsigned long right = 0L; 54.165 + pseudo_des(&left, &right); 54.166 + return right; 54.167 +#else 54.168 + a = lcrng_hash(a); 54.169 + a = lcrng_hash(a); 54.170 + return a; 54.171 +#endif 54.172 +} 54.173 + 54.174 +/** Hash two unsigned longs together. 54.175 + * 54.176 + * @param a input to hash 54.177 + * @param b input to hash 54.178 + * @return hashcode 54.179 + */ 54.180 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){ 54.181 +#if HASH_PSEUDO_DES 54.182 + unsigned long left = a; 54.183 + unsigned long right = b; 54.184 + pseudo_des(&left, &right); 54.185 + return right; 54.186 +#else 54.187 + a = lcrng_hash(a); 54.188 + a ^= b; 54.189 + a = lcrng_hash(a); 54.190 + return a; 54.191 +#endif 54.192 +} 54.193 + 54.194 +/** Hash a hashcode and an unsigned long together. 54.195 + * 54.196 + * @param a input hashcode 54.197 + * @param b input to hash 54.198 + * @return hashcode 54.199 + */ 54.200 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){ 54.201 +#if HASH_PSEUDO_DES 54.202 + unsigned long left = a; 54.203 + unsigned long right = b; 54.204 + pseudo_des(&left, &right); 54.205 + return right; 54.206 +#else 54.207 + a ^= b; 54.208 + a = lcrng_hash(a); 54.209 + return a; 54.210 +#endif 54.211 +} 54.212 + 54.213 +/** Macro to declare variables for HashTable_for_each() to use. 54.214 + * 54.215 + * @param entry variable that is set to entries in the table 54.216 + */ 54.217 +#define HashTable_for_decl(entry) \ 54.218 + HashTable *_var_table; \ 54.219 + HTBucket *_var_bucket; \ 54.220 + HTBucket *_var_end; \ 54.221 + HTEntry *_var_next; \ 54.222 + HTEntry *entry 54.223 + 54.224 +/** Macro to iterate over the entries in a hashtable. 54.225 + * Must be in a scope where HashTable_for_decl() has been used to declare 54.226 + * variables for it to use. 54.227 + * The variable 'entry' is iterated over entries in the table. 54.228 + * The code produced is syntactically a loop, so it must be followed by 54.229 + * a loop body, typically some statements in braces: 54.230 + * HashTable_for_each(entry, table){ ...loop body... } 54.231 + * 54.232 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested 54.233 + * loops as variables will clash. 54.234 + * 54.235 + * @note The simplest way to code a direct loop over the entries in a hashtable 54.236 + * is to use a loop over the buckets, with a nested loop over the entries 54.237 + * in a bucket. Using this approach in a macro means the macro contains 54.238 + * an opening brace, and calls to it must be followed by 2 braces! 54.239 + * To avoid this the code has been restructured so that it is a for loop. 54.240 + * So that statements could be used in the test expression of the for loop, 54.241 + * we have used the gcc statement expression extension ({ ... }). 54.242 + * 54.243 + * @param entry variable to iterate over the entries 54.244 + * @param table to iterate over (non-null) 54.245 + */ 54.246 +#define HashTable_for_each(entry, table) \ 54.247 + _var_table = table; \ 54.248 + _var_bucket = _var_table->buckets; \ 54.249 + _var_end = _var_bucket + _var_table->buckets_n; \ 54.250 + for(entry=0, _var_next=0; \ 54.251 + ({ if(_var_next){ \ 54.252 + entry = _var_next; \ 54.253 + _var_next = entry->next; \ 54.254 + } else { \ 54.255 + while(_var_bucket < _var_end){ \ 54.256 + entry = _var_bucket->head; \ 54.257 + _var_bucket++; \ 54.258 + if(entry){ \ 54.259 + _var_next = entry->next; \ 54.260 + break; \ 54.261 + } \ 54.262 + } \ 54.263 + }; \ 54.264 + entry; }); \ 54.265 + entry = _var_next ) 54.266 + 54.267 +/** Map a function over the entries in a table. 54.268 + * Mapping stops when the function returns a non-zero value. 54.269 + * Uses the gcc statement expression extension ({ ... }). 54.270 + * 54.271 + * @param table to map over 54.272 + * @param fn function to apply to entries 54.273 + * @param arg first argument to call the function with 54.274 + * @return 0 if fn always returned 0, first non-zero value otherwise 54.275 + */ 54.276 +#define HashTable_map(table, fn, arg) \ 54.277 + ({ HashTable_for_decl(_var_entry); \ 54.278 + TableArg _var_arg = arg; \ 54.279 + int _var_value = 0; \ 54.280 + HashTable_for_each(_var_entry, table){ \ 54.281 + if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \ 54.282 + } \ 54.283 + _var_value; }) 54.284 + 54.285 +/** Cast x to the type for a key or value in a hash table. 54.286 + * This avoids compiler warnings when using short integers 54.287 + * as keys or values (especially on 64-bit platforms). 54.288 + */ 54.289 +#define HKEY(x) ((void*)(unsigned long)(x)) 54.290 + 54.291 +/** Cast x from the type for a key or value in a hash table. 54.292 + * to an unsigned long. This avoids compiler warnings when using 54.293 + * short integers as keys or values (especially on 64-bit platforms). 54.294 + */ 54.295 +#define HVAL(x) ((unsigned long)(x)) 54.296 + 54.297 +#endif /* !_XUTIL_HASH_TABLE_H_ */
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/tools/xfrd/lexis.c Tue Jul 06 17:27:27 2004 +0000 55.3 @@ -0,0 +1,93 @@ 55.4 +/* 55.5 + * 55.6 + * This library is free software; you can redistribute it and/or modify 55.7 + * it under the terms of the GNU Lesser General Public License as 55.8 + * published by the Free Software Foundation; either version 2.1 of the 55.9 + * License, or (at your option) any later version. This library is 55.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 55.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 55.12 + * FITNESS FOR A PARTICULAR PURPOSE. 55.13 + * See the GNU Lesser General Public License for more details. 55.14 + * 55.15 + * You should have received a copy of the GNU Lesser General Public License 55.16 + * along with this library; if not, write to the Free Software Foundation, 55.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 55.18 + */ 55.19 + 55.20 +/** @file 55.21 + * Lexical analysis. 55.22 + */ 55.23 + 55.24 +#include "sys_string.h" 55.25 +#include "lexis.h" 55.26 +#include <errno.h> 55.27 + 55.28 +/** Check if a value lies in a (closed) range. 55.29 + * 55.30 + * @param x value to test 55.31 + * @param lo low end of the range 55.32 + * @param hi high end of the range 55.33 + * @return 1 if x is in the interval [lo, hi], 0 otherwise 55.34 + */ 55.35 +inline static int in_range(int x, int lo, int hi){ 55.36 + return (lo <= x) && (x <= hi); 55.37 +} 55.38 + 55.39 +/** Determine if a string is an (unsigned) decimal number. 55.40 + * 55.41 + * @param s pointer to characters to test 55.42 + * @param n length of string 55.43 + * @return 1 if s is a decimal number, 0 otherwise. 55.44 + */ 55.45 +int is_decimal_number(const char *s, int n){ 55.46 + int i; 55.47 + if(n <= 0)return 0; 55.48 + for(i = 0; i < n; i++){ 55.49 + if(!in_decimal_digit_class(s[i])) return 0; 55.50 + } 55.51 + return 1; 55.52 +} 55.53 + 55.54 +/** Determine if a string is a hex number. 55.55 + * Hex numbers are 0, or start with 0x or 0X followed 55.56 + * by a non-zero number of hex digits (0-9,a-f,A-F). 55.57 + * 55.58 + * @param s pointer to characters to test 55.59 + * @param n length of string 55.60 + * @return 1 if s is a hex number, 0 otherwise. 55.61 + */ 55.62 +int is_hex_number(const char *s, int n){ 55.63 + int i; 55.64 + if(n <= 0) return 0; 55.65 + if(n == 1){ 55.66 + return s[0]=='0'; 55.67 + } 55.68 + if(n <= 3) return 0; 55.69 + if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0; 55.70 + for(i = 2; i < n; i++){ 55.71 + if(!in_hex_digit_class(s[i])) return 0; 55.72 + } 55.73 + return 1; 55.74 +} 55.75 + 55.76 +/** Test if a string matches a keyword. 55.77 + * The comparison is case-insensitive. 55.78 + * The comparison fails if either argument is null. 55.79 + * 55.80 + * @param s string 55.81 + * @param k keyword 55.82 + * @return 1 if they match, 0 otherwise 55.83 + */ 55.84 +int is_keyword(const char *s, const char *k){ 55.85 + return s && k && !strcasecmp(s, k); 55.86 +} 55.87 + 55.88 +/** Test if a string matches a character. 55.89 + * 55.90 + * @param s string 55.91 + * @param c character (non-null) 55.92 + * @return 1 if s contains exactly c, 0 otherwise 55.93 + */ 55.94 +int is_keychar(const char *s, char c){ 55.95 + return c && (s[0] == c) && !s[1]; 55.96 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/tools/xfrd/lexis.h Tue Jul 06 17:27:27 2004 +0000 56.3 @@ -0,0 +1,127 @@ 56.4 +/* 56.5 + * 56.6 + * This library is free software; you can redistribute it and/or modify 56.7 + * it under the terms of the GNU Lesser General Public License as 56.8 + * published by the Free Software Foundation; either version 2.1 of the 56.9 + * License, or (at your option) any later version. This library is 56.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 56.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 56.12 + * FITNESS FOR A PARTICULAR PURPOSE. 56.13 + * See the GNU Lesser General Public License for more details. 56.14 + * 56.15 + * You should have received a copy of the GNU Lesser General Public License 56.16 + * along with this library; if not, write to the Free Software Foundation, 56.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 56.18 + */ 56.19 + 56.20 +#ifndef _XUTIL_LEXIS_H_ 56.21 +#define _XUTIL_LEXIS_H_ 56.22 + 56.23 +#include "sys_string.h" 56.24 + 56.25 +#ifdef __KERNEL__ 56.26 +# include <linux/ctype.h> 56.27 +#else 56.28 +# include <ctype.h> 56.29 +#endif 56.30 + 56.31 +/** @file 56.32 + * Lexical analysis. 56.33 + */ 56.34 + 56.35 +/** Class of characters treated as space. */ 56.36 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 }) 56.37 + 56.38 +/** Class of separator characters. */ 56.39 +#define sep_class "{}()<>[]@!;" 56.40 + 56.41 +#define comment_class "#" 56.42 + 56.43 +/** Determine if a character is in a given class. 56.44 + * 56.45 + * @param c character to test 56.46 + * @param s null-terminated string of characters in the class 56.47 + * @return 1 if c is in the class, 0 otherwise. 56.48 + */ 56.49 +static inline int in_class(int c, const char *s){ 56.50 + return s && (strchr(s, c) != 0); 56.51 +} 56.52 + 56.53 +/** Determine if a character is in the space class. 56.54 + * 56.55 + * @param c character to test 56.56 + * @return 1 if c is in the class, 0 otherwise. 56.57 + */ 56.58 +static inline int in_space_class(int c){ 56.59 + return in_class(c, space_class); 56.60 +} 56.61 + 56.62 +static inline int in_comment_class(int c){ 56.63 + return in_class(c, comment_class); 56.64 +} 56.65 + 56.66 +/** Determine if a character is in the separator class. 56.67 + * Separator characters terminate tokens, and do not need space 56.68 + * to separate them. 56.69 + * 56.70 + * @param c character to test 56.71 + * @return 1 if c is in the class, 0 otherwise. 56.72 + */ 56.73 +static inline int in_sep_class(int c){ 56.74 + return in_class(c, sep_class); 56.75 +} 56.76 + 56.77 +/** Determine if a character is in the alpha class. 56.78 + * 56.79 + * @param c character to test 56.80 + * @return 1 if c is in the class, 0 otherwise. 56.81 + */ 56.82 +static inline int in_alpha_class(int c){ 56.83 + return isalpha(c); 56.84 +} 56.85 + 56.86 +/** Determine if a character is in the octal digit class. 56.87 + * 56.88 + * @param c character to test 56.89 + * @return 1 if c is in the class, 0 otherwise. 56.90 + */ 56.91 +static inline int in_octal_digit_class(int c){ 56.92 + return '0' <= c && c <= '7'; 56.93 +} 56.94 + 56.95 +/** Determine if a character is in the decimal digit class. 56.96 + * 56.97 + * @param c character to test 56.98 + * @return 1 if c is in the class, 0 otherwise. 56.99 + */ 56.100 +static inline int in_decimal_digit_class(int c){ 56.101 + return isdigit(c); 56.102 +} 56.103 + 56.104 +/** Determine if a character is in the hex digit class. 56.105 + * 56.106 + * @param c character to test 56.107 + * @return 1 if c is in the class, 0 otherwise. 56.108 + */ 56.109 +static inline int in_hex_digit_class(int c){ 56.110 + return isdigit(c) || in_class(c, "abcdefABCDEF"); 56.111 +} 56.112 + 56.113 + 56.114 +static inline int in_string_quote_class(int c){ 56.115 + return in_class(c, "'\""); 56.116 +} 56.117 + 56.118 +static inline int in_printable_class(int c){ 56.119 + return ('A' <= c && c <= 'Z') 56.120 + || ('a' <= c && c <= 'z') 56.121 + || ('0' <= c && c <= '9') 56.122 + || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~"); 56.123 +} 56.124 + 56.125 +extern int is_decimal_number(const char *s, int n); 56.126 +extern int is_hex_number(const char *s, int n); 56.127 +extern int is_keyword(const char *s, const char *k); 56.128 +extern int is_keychar(const char *s, char c); 56.129 + 56.130 +#endif /* !_XUTIL_LEXIS_H_ */
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/tools/xfrd/lzi_stream.c Tue Jul 06 17:27:27 2004 +0000 57.3 @@ -0,0 +1,533 @@ 57.4 +/* 57.5 + * Copyright (C) 2003 Hewlett-Packard Company. 57.6 + * 57.7 + * This library is free software; you can redistribute it and/or modify 57.8 + * it under the terms of the GNU Lesser General Public License as published by 57.9 + * the Free Software Foundation; either version 2.1 of the License, or 57.10 + * (at your option) any later version. 57.11 + * 57.12 + * This library is distributed in the hope that it will be useful, 57.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 57.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 57.15 + * GNU Lesser General Public License for more details. 57.16 + * 57.17 + * You should have received a copy of the GNU Lesser General Public License 57.18 + * along with this library; if not, write to the Free Software 57.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 57.20 + */ 57.21 + 57.22 +/** @file 57.23 + * An IOStream implementation using LZI to provide compression and decompression. 57.24 + * This is designed to provide compression without output latency. 57.25 + * Flushing an LZI stream flushes all pending data to the underlying stream. 57.26 + * This is essential for stream-based (e.g. networked) applications. 57.27 + * 57.28 + * A compressed data stream is a sequence of blocks. 57.29 + * Each block is the block size followed by the compressed data. 57.30 + * The last block has size zero. 57.31 + * Sizes are 4-byte unsigned in network order. 57.32 + * 57.33 + * This format allows compressed data to be read from a stream without reading 57.34 + * past the logical end of compressed data. 57.35 + * 57.36 + * @author Mike Wray <mike.wray@hpl.hp.com> 57.37 + */ 57.38 +#ifndef __KERNEL__ 57.39 + 57.40 +#include <stdio.h> 57.41 +#include <stdlib.h> 57.42 +#include <errno.h> 57.43 +#include <string.h> 57.44 + 57.45 +#include "zlib.h" 57.46 + 57.47 +#include "allocate.h" 57.48 +#include "lzi_stream.h" 57.49 +#include "file_stream.h" 57.50 +#include "marshal.h" 57.51 + 57.52 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZI>%s" fmt, __FUNCTION__, ##args) 57.53 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN] LZI>%s" fmt, __FUNCTION__, ##args) 57.54 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO] LZI>%s" fmt, __FUNCTION__, ##args) 57.55 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZI>%s" fmt, __FUNCTION__, ##args) 57.56 + 57.57 +static int lzi_read(IOStream *s, void *buf, size_t n); 57.58 +static int lzi_write(IOStream *s, const void *buf, size_t n); 57.59 +static int lzi_error(IOStream *s); 57.60 +static int lzi_close(IOStream *s); 57.61 +static void lzi_free(IOStream *s); 57.62 +static int lzi_flush(IOStream *s); 57.63 + 57.64 +enum { 57.65 + LZI_WRITE = 1, 57.66 + LZI_READ = 2, 57.67 +}; 57.68 + 57.69 +/** Methods used by a gzFile* IOStream. */ 57.70 +static const IOMethods lzi_methods = { 57.71 + read: lzi_read, 57.72 + write: lzi_write, 57.73 + error: lzi_error, 57.74 + close: lzi_close, 57.75 + free: lzi_free, 57.76 + flush: lzi_flush, 57.77 +}; 57.78 + 57.79 +#define BUFFER_SIZE (512 * 1024) 57.80 + 57.81 +typedef struct LZIState { 57.82 + z_stream zstream; 57.83 + void *inbuf; 57.84 + uint32_t inbuf_size; 57.85 + void *outbuf; 57.86 + uint32_t outbuf_size; 57.87 + /** Underlying stream for I/O. */ 57.88 + IOStream *io; 57.89 + /** Flags. */ 57.90 + int flags; 57.91 + /** Error indicator. */ 57.92 + int error; 57.93 + int eof; 57.94 + int plain_bytes; 57.95 + int comp_bytes; 57.96 + int zstream_initialized; 57.97 + int flushed; 57.98 +} LZIState; 57.99 + 57.100 +static inline int LZIState_writeable(LZIState *s){ 57.101 + return (s->flags & LZI_WRITE) != 0; 57.102 +} 57.103 + 57.104 +static inline int LZIState_readable(LZIState *s){ 57.105 + return (s->flags & LZI_READ) != 0; 57.106 +} 57.107 + 57.108 +void LZIState_free(LZIState *z){ 57.109 + if(!z) return; 57.110 + if(z->zstream_initialized){ 57.111 + if(LZIState_writeable(z)){ 57.112 + deflateEnd(&z->zstream); 57.113 + } else if(LZIState_readable(z)){ 57.114 + inflateEnd(&z->zstream); 57.115 + } 57.116 + } 57.117 + deallocate(z->inbuf); 57.118 + deallocate(z->outbuf); 57.119 + deallocate(z); 57.120 +} 57.121 + 57.122 +static int mode_flags(const char *mode, int *flags){ 57.123 + int err = 0; 57.124 + int r=0, w=0; 57.125 + if(!mode){ 57.126 + err = -EINVAL; 57.127 + goto exit; 57.128 + } 57.129 + for(; *mode; mode++){ 57.130 + if(*mode == 'w') w = 1; 57.131 + if(*mode == 'r') r = 1; 57.132 + } 57.133 + if(r + w != 1){ 57.134 + err = -EINVAL; 57.135 + goto exit; 57.136 + } 57.137 + if(r) *flags |= LZI_READ; 57.138 + if(w) *flags |= LZI_WRITE; 57.139 + exit: 57.140 + return err; 57.141 +} 57.142 + 57.143 +/** Get the stream state. 57.144 + * 57.145 + * @param s lzi stream 57.146 + * @return stream state. 57.147 + */ 57.148 +static inline LZIState * lzi_state(IOStream *io){ 57.149 + return (LZIState*)io->data; 57.150 +} 57.151 + 57.152 +IOStream *lzi_stream_io(IOStream *io){ 57.153 + LZIState *s = lzi_state(io); 57.154 + return s->io; 57.155 +} 57.156 + 57.157 +static inline void set_error(LZIState *s, int err){ 57.158 + if(err < 0 && !s->error){ 57.159 + s->error = err; 57.160 + } 57.161 +} 57.162 + 57.163 +static int zerror(LZIState *s, int err){ 57.164 + if(err){ 57.165 + //dprintf("> err=%d\n", err); 57.166 + if(err < 0) set_error(s, -EIO); 57.167 + } 57.168 + return s->error; 57.169 +} 57.170 + 57.171 +int lzi_stream_plain_bytes(IOStream *io){ 57.172 + LZIState *s = lzi_state(io); 57.173 + return s->plain_bytes; 57.174 +} 57.175 + 57.176 +int lzi_stream_comp_bytes(IOStream *io){ 57.177 + LZIState *s = lzi_state(io); 57.178 + return s->comp_bytes; 57.179 +} 57.180 + 57.181 +float lzi_stream_ratio(IOStream *io){ 57.182 + LZIState *s = lzi_state(io); 57.183 + float ratio = 0.0; 57.184 + if(s->comp_bytes){ 57.185 + ratio = ((float) s->comp_bytes)/((float) s->plain_bytes); 57.186 + } 57.187 + return ratio; 57.188 +} 57.189 + 57.190 +static int alloc(void **p, int n){ 57.191 + *p = allocate(n); 57.192 + return (p ? 0 : -ENOMEM); 57.193 +} 57.194 + 57.195 +LZIState * LZIState_new(IOStream *io, int flags){ 57.196 + int err = -ENOMEM; 57.197 + int zlevel = Z_BEST_SPEED; // Level 1 compression - fastest. 57.198 + int zstrategy = Z_DEFAULT_STRATEGY; 57.199 + int zwindow = MAX_WBITS; 57.200 + int zmemory = 8; 57.201 + LZIState *z = ALLOCATE(LZIState); 57.202 + 57.203 + //dprintf(">\n"); 57.204 + if(!z) goto exit; 57.205 + z->io = io; 57.206 + z->flags = flags; 57.207 + 57.208 + if(LZIState_writeable(z)){ 57.209 + z->outbuf_size = BUFFER_SIZE; 57.210 + /* windowBits is passed < 0 to suppress zlib header */ 57.211 + err = deflateInit2(&z->zstream, zlevel, Z_DEFLATED, -zwindow, zmemory, zstrategy); 57.212 + if (err != Z_OK) goto exit; 57.213 + z->zstream_initialized = 1; 57.214 + err = alloc(&z->outbuf, z->outbuf_size); 57.215 + if(err) goto exit; 57.216 + z->zstream.next_out = z->outbuf; 57.217 + z->zstream.avail_out = z->outbuf_size; 57.218 + } else { 57.219 + z->inbuf_size = BUFFER_SIZE; 57.220 + err = alloc(&z->inbuf, z->inbuf_size); 57.221 + if(err) goto exit; 57.222 + ///z->zstream.next_in = z->inbuf; 57.223 + 57.224 + /* windowBits is passed < 0 to tell that there is no zlib header. 57.225 + * Note that in this case inflate *requires* an extra "dummy" byte 57.226 + * after the compressed stream in order to complete decompression and 57.227 + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are 57.228 + * present after the compressed stream. 57.229 + */ 57.230 + err = inflateInit2(&z->zstream, -zwindow); 57.231 + if(err != Z_OK) goto exit; 57.232 + z->zstream_initialized = 1; 57.233 + } 57.234 + 57.235 + exit: 57.236 + if(err){ 57.237 + LZIState_free(z); 57.238 + z = NULL; 57.239 + } 57.240 + //dprintf("< z=%p\n", z); 57.241 + return z; 57.242 +} 57.243 + 57.244 +int read_block(LZIState *s){ 57.245 + int err = 0, k = 0; 57.246 + //dprintf(">\n"); 57.247 + if(s->eof) goto exit; 57.248 + err = unmarshal_uint32(s->io, &k); 57.249 + if(err) goto exit; 57.250 + if(k > s->inbuf_size){ 57.251 + err = -EINVAL; 57.252 + goto exit; 57.253 + } 57.254 + if(k){ 57.255 + err = unmarshal_bytes(s->io, s->inbuf, k); 57.256 + if(err) goto exit; 57.257 + } else { 57.258 + s->eof = 1; 57.259 + } 57.260 + s->zstream.avail_in = k; 57.261 + s->zstream.next_in = s->inbuf; 57.262 + s->comp_bytes += 4; 57.263 + s->comp_bytes += k; 57.264 + exit: 57.265 + //dprintf("< err=%d\n", err); 57.266 + return err; 57.267 +} 57.268 + 57.269 +int write_block(LZIState *s){ 57.270 + int err = 0; 57.271 + int k = ((char*)s->zstream.next_out) - ((char*)s->outbuf); 57.272 + //int k2 = s->outbuf_size - s->zstream.avail_out; 57.273 + //dprintf("> k=%d k2=%d\n", k, k2); 57.274 + if(!k) goto exit; 57.275 + err = marshal_uint32(s->io, k); 57.276 + if(err) goto exit; 57.277 + err = marshal_bytes(s->io, s->outbuf, k); 57.278 + if(err) goto exit; 57.279 + s->zstream.next_out = s->outbuf; 57.280 + s->zstream.avail_out = s->outbuf_size; 57.281 + s->comp_bytes += 4; 57.282 + s->comp_bytes += k; 57.283 + exit: 57.284 + //dprintf("< err=%d\n", err); 57.285 + return err; 57.286 +} 57.287 + 57.288 +int write_terminator(LZIState *s){ 57.289 + int err = 0; 57.290 + char c = 0; 57.291 + err = marshal_uint32(s->io, 1); 57.292 + if(err) goto exit; 57.293 + err = marshal_bytes(s->io, &c, 1); 57.294 + if(err) goto exit; 57.295 + err = marshal_uint32(s->io, 0); 57.296 + if(err) goto exit; 57.297 + s->comp_bytes += 9; 57.298 + exit: 57.299 + return err; 57.300 +} 57.301 + 57.302 +/** Write to the underlying stream using fwrite(); 57.303 + * 57.304 + * @param io destination 57.305 + * @param buf data 57.306 + * @param n number of bytes to write 57.307 + * @return number of bytes written 57.308 + */ 57.309 +static int lzi_write(IOStream *io, const void *buf, size_t n){ 57.310 + int err = 0; 57.311 + LZIState *s = lzi_state(io); 57.312 + 57.313 + //dprintf("> buf=%p n=%d\n", buf, n); 57.314 + if(!LZIState_writeable(s)){ 57.315 + err = -EINVAL; 57.316 + goto exit; 57.317 + } 57.318 + s->flushed = 0; 57.319 + s->zstream.next_in = (void*)buf; 57.320 + s->zstream.avail_in = n; 57.321 + while(s->zstream.avail_in){ 57.322 + if(s->zstream.avail_out == 0){ 57.323 + err = write_block(s); 57.324 + if(err) goto exit; 57.325 + } 57.326 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.327 + //dprintf("> 1 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out); 57.328 + err = zerror(s, deflate(&s->zstream, Z_NO_FLUSH)); 57.329 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.330 + //dprintf("> 2 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out); 57.331 + if(err) goto exit; 57.332 + } 57.333 + err = n; 57.334 + s->plain_bytes += n; 57.335 + exit: 57.336 + //dprintf("< err=%d\n", err); 57.337 + return err; 57.338 +} 57.339 + 57.340 + 57.341 +/** Read from the underlying stream. 57.342 + * 57.343 + * @param io input 57.344 + * @param buf where to put input 57.345 + * @param n number of bytes to read 57.346 + * @return number of bytes read 57.347 + */ 57.348 +static int lzi_read(IOStream *io, void *buf, size_t n){ 57.349 + int err, zerr; 57.350 + LZIState *s = lzi_state(io); 57.351 + 57.352 + //dprintf("> n=%d\n", n); 57.353 + if(!LZIState_readable(s)){ 57.354 + err = -EINVAL; 57.355 + goto exit; 57.356 + } 57.357 + s->zstream.next_out = buf; 57.358 + s->zstream.avail_out = n; 57.359 + while(s->zstream.avail_out){ 57.360 + if(s->zstream.avail_in == 0){ 57.361 + err = read_block(s); 57.362 + } 57.363 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.364 + zerr = inflate(&s->zstream, Z_NO_FLUSH); 57.365 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.366 + if(zerr == Z_STREAM_END) break; 57.367 + //dprintf("> zerr=%d\n", zerr); 57.368 + err = zerror(s, zerr); 57.369 + if(err) goto exit; 57.370 + } 57.371 + err = n - s->zstream.avail_out; 57.372 + s->plain_bytes += err; 57.373 + exit: 57.374 + set_error(s, err); 57.375 + //dprintf("< err=%d\n", err); 57.376 + return err; 57.377 +} 57.378 + 57.379 +static int flush_output(LZIState *s, int mode){ 57.380 + int err = 0, zerr; 57.381 + int done = 0; 57.382 + int avail_out_old; 57.383 + 57.384 + //dprintf("> avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.385 + if(s->flushed == 1 + mode) goto exit; 57.386 + //s->zstream.avail_in = 0; /* should be zero already anyway */ 57.387 + for(;;){ 57.388 + // Write any available output. 57.389 + if(done || s->zstream.avail_out == 0){ 57.390 + err = write_block(s); 57.391 + if(err) goto exit; 57.392 + if(done) break; 57.393 + } 57.394 + //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.395 + avail_out_old = s->zstream.avail_out; 57.396 + zerr = deflate(&s->zstream, mode); 57.397 + err = zerror(s, zerr); 57.398 + //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out); 57.399 + //dprintf("> deflate=%d\n", err); 57.400 + //done = (s->zstream.avail_out != 0); 57.401 + //done = (s->zstream.avail_in == 0) && (s->zstream.avail_out == avail_out_old); 57.402 + if(0 && mode == Z_FINISH){ 57.403 + done = (zerr == Z_STREAM_END); 57.404 + } else { 57.405 + done = (s->zstream.avail_in == 0) 57.406 + //&& (s->zstream.avail_out == avail_out_old) 57.407 + && (s->zstream.avail_out != 0); 57.408 + } 57.409 + } 57.410 + s->flushed = 1 + mode; 57.411 + exit: 57.412 + //dprintf("< err=%d\n", err); 57.413 + return err; 57.414 +} 57.415 + 57.416 +/** Flush any pending input to the underlying stream. 57.417 + * 57.418 + * @param s lzi stream 57.419 + * @return 0 on success, error code otherwise 57.420 + */ 57.421 +static int lzi_flush(IOStream *io){ 57.422 + int err = 0; 57.423 + LZIState *s = lzi_state(io); 57.424 + //dprintf(">\n"); 57.425 + if(!LZIState_writeable(s)){ 57.426 + err = -EINVAL; 57.427 + goto exit; 57.428 + } 57.429 + err = flush_output(s, Z_SYNC_FLUSH); 57.430 + if(err) goto exit; 57.431 + err = IOStream_flush(s->io); 57.432 + exit: 57.433 + set_error(s, err); 57.434 + //dprintf("< err=%d\n", err); 57.435 + return (err < 0 ? err : 0); 57.436 +} 57.437 + 57.438 +/** Check if a stream has an error. 57.439 + * 57.440 + * @param s lzi stream 57.441 + * @return code if has an error, 0 otherwise 57.442 + */ 57.443 +static int lzi_error(IOStream *s){ 57.444 + int err = 0; 57.445 + LZIState *state = lzi_state(s); 57.446 + err = state->error; 57.447 + if(err) goto exit; 57.448 + err = IOStream_error(state->io); 57.449 + exit: 57.450 + return err; 57.451 +} 57.452 + 57.453 +/** Close an lzi stream. 57.454 + * 57.455 + * @param s lzi stream to close 57.456 + * @return result of the close 57.457 + */ 57.458 +static int lzi_close(IOStream *io){ 57.459 + int err = 0; 57.460 + LZIState *s = lzi_state(io); 57.461 + if(LZIState_writeable(s)){ 57.462 + err = flush_output(s, Z_FINISH); 57.463 + if(err) goto exit; 57.464 + err = write_terminator(s); 57.465 + if(err) goto exit; 57.466 + err = IOStream_flush(s->io); 57.467 + } 57.468 + exit: 57.469 + err = IOStream_close(s->io); 57.470 + set_error(s, err); 57.471 + return err; 57.472 +} 57.473 + 57.474 +/** Free an lzi stream. 57.475 + * 57.476 + * @param s lzi stream 57.477 + */ 57.478 +static void lzi_free(IOStream *s){ 57.479 + LZIState *state = lzi_state(s); 57.480 + IOStream_free(state->io); 57.481 + LZIState_free(state); 57.482 + s->data = NULL; 57.483 +} 57.484 + 57.485 +/** Create an lzi stream for an IOStream. 57.486 + * 57.487 + * @param io stream to wrap 57.488 + * @return new IOStream using f for i/o 57.489 + */ 57.490 +IOStream *lzi_stream_new(IOStream *io, const char *mode){ 57.491 + int err = -ENOMEM; 57.492 + int flags = 0; 57.493 + IOStream *zio = NULL; 57.494 + LZIState *state = NULL; 57.495 + 57.496 + zio = ALLOCATE(IOStream); 57.497 + if(!zio) goto exit; 57.498 + err = mode_flags(mode, &flags); 57.499 + if(err) goto exit; 57.500 + state = LZIState_new(io, flags); 57.501 + if(!state) goto exit; 57.502 + err = 0; 57.503 + zio->data = state; 57.504 + zio->methods = &lzi_methods; 57.505 + exit: 57.506 + if(err){ 57.507 + if(state) LZIState_free(state); 57.508 + if(zio) deallocate(zio); 57.509 + zio = NULL; 57.510 + } 57.511 + return zio; 57.512 +} 57.513 + 57.514 +/** IOStream version of fdopen(). 57.515 + * 57.516 + * @param fd file descriptor 57.517 + * @param flags giving the mode to open in (as for fdopen()) 57.518 + * @return new stream for the open file, or NULL if failed 57.519 + */ 57.520 +IOStream *lzi_stream_fdopen(int fd, const char *mode){ 57.521 + int err = -ENOMEM; 57.522 + IOStream *io = NULL, *zio = NULL; 57.523 + io = file_stream_fdopen(fd, mode); 57.524 + if(!io) goto exit; 57.525 + zio = lzi_stream_new(io, mode); 57.526 + if(!io) goto exit; 57.527 + err = 0; 57.528 + exit: 57.529 + if(err){ 57.530 + IOStream_free(io); 57.531 + IOStream_free(zio); 57.532 + zio = NULL; 57.533 + } 57.534 + return zio; 57.535 +} 57.536 +#endif
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 58.2 +++ b/tools/xfrd/lzi_stream.h Tue Jul 06 17:27:27 2004 +0000 58.3 @@ -0,0 +1,35 @@ 58.4 +/* 58.5 + * Copyright (C) 2003 Hewlett-Packard Company. 58.6 + * 58.7 + * This library is free software; you can redistribute it and/or modify 58.8 + * it under the terms of the GNU Lesser General Public License as published by 58.9 + * the Free Software Foundation; either version 2.1 of the License, or 58.10 + * (at your option) any later version. 58.11 + * 58.12 + * This library is distributed in the hope that it will be useful, 58.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 58.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 58.15 + * GNU Lesser General Public License for more details. 58.16 + * 58.17 + * You should have received a copy of the GNU Lesser General Public License 58.18 + * along with this library; if not, write to the Free Software 58.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 58.20 + */ 58.21 + 58.22 +#ifndef _XUTIL_LZI_STREAM_H_ 58.23 +#define _XUTIL_LZI_STREAM_H_ 58.24 + 58.25 +#ifndef __KERNEL__ 58.26 +#include "iostream.h" 58.27 + 58.28 +extern IOStream *lzi_stream_new(IOStream *io, const char *mode); 58.29 +extern IOStream *lzi_stream_fopen(const char *file, const char *mode); 58.30 +extern IOStream *lzi_stream_fdopen(int fd, const char *mode); 58.31 +extern IOStream *lzi_stream_io(IOStream *zio); 58.32 + 58.33 +extern int lzi_stream_plain_bytes(IOStream *io); 58.34 +extern int lzi_stream_comp_bytes(IOStream *io); 58.35 +extern float lzi_stream_ratio(IOStream *io); 58.36 + 58.37 +#endif 58.38 +#endif /* !_XUTIL_LZI_STREAM_H_ */
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 59.2 +++ b/tools/xfrd/marshal.c Tue Jul 06 17:27:27 2004 +0000 59.3 @@ -0,0 +1,207 @@ 59.4 +#include <errno.h> 59.5 +#include "sys_net.h" 59.6 +#include "allocate.h" 59.7 +#include "marshal.h" 59.8 + 59.9 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args) 59.10 +#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN] %s" fmt, __FUNCTION__, ##args) 59.11 +#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO] %s" fmt, __FUNCTION__, ##args) 59.12 +#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args) 59.13 + 59.14 + 59.15 +#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0])) 59.16 + 59.17 +/* Messages are coded as msgid followed by message fields. 59.18 + * Initial message on any channel is hello - so can check version 59.19 + * compatibility. 59.20 + * 59.21 + * char* -> uint16_t:n <n bytes> 59.22 + * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes). 59.23 + * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte). 59.24 + * lists go as ('1' <elt>)* '0' 59.25 + */ 59.26 + 59.27 +int marshal_flush(IOStream *io){ 59.28 + int err = 0; 59.29 + err = IOStream_flush(io); 59.30 + return err; 59.31 +} 59.32 + 59.33 +int marshal_bytes(IOStream *io, void *s, uint32_t s_n){ 59.34 + int err = 0; 59.35 + int n; 59.36 + n = IOStream_write(io, s, s_n); 59.37 + if(n < 0){ 59.38 + err = n; 59.39 + } else if (n < s_n){ 59.40 + wprintf("> Wanted %d, got %d\n", s_n, n); 59.41 + err = -EIO; 59.42 + } 59.43 + return err; 59.44 +} 59.45 + 59.46 +int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){ 59.47 + int err = 0; 59.48 + int n; 59.49 + //dprintf("> s_n=%d\n", s_n); 59.50 + n = IOStream_read(io, s, s_n); 59.51 + //dprintf("> n=%d\n", n); 59.52 + if(n < 0){ 59.53 + err = n; 59.54 + } else if(n < s_n){ 59.55 + wprintf("> Wanted %d, got %d\n", s_n, n); 59.56 + err = -EIO; 59.57 + } 59.58 + //dprintf("< err=%d\n", err); 59.59 + return err; 59.60 +} 59.61 + 59.62 +int marshal_uint8(IOStream *io, uint8_t x){ 59.63 + return marshal_bytes(io, &x, sizeof(x)); 59.64 +} 59.65 + 59.66 +int unmarshal_uint8(IOStream *io, uint8_t *x){ 59.67 + return unmarshal_bytes(io, x, sizeof(*x)); 59.68 +} 59.69 + 59.70 +int marshal_uint16(IOStream *io, uint16_t x){ 59.71 + x = htons(x); 59.72 + return marshal_bytes(io, &x, sizeof(x)); 59.73 +} 59.74 + 59.75 +int unmarshal_uint16(IOStream *io, uint16_t *x){ 59.76 + int err = 0; 59.77 + err = unmarshal_bytes(io, x, sizeof(*x)); 59.78 + *x = ntohs(*x); 59.79 + return err; 59.80 +} 59.81 + 59.82 +int marshal_int32(IOStream *io, int32_t x){ 59.83 + int err = 0; 59.84 + //dprintf("> x=%d\n", x); 59.85 + x = htonl(x); 59.86 + err = marshal_bytes(io, &x, sizeof(x)); 59.87 + //dprintf("< err=%d\n", err); 59.88 + return err; 59.89 +} 59.90 + 59.91 +int unmarshal_int32(IOStream *io, int32_t *x){ 59.92 + int err = 0; 59.93 + //dprintf(">\n"); 59.94 + err = unmarshal_bytes(io, x, sizeof(*x)); 59.95 + *x = ntohl(*x); 59.96 + //dprintf("< err=%d x=%d\n", err, *x); 59.97 + return err; 59.98 +} 59.99 + 59.100 +int marshal_uint32(IOStream *io, uint32_t x){ 59.101 + int err = 0; 59.102 + //dprintf("> x=%u\n", x); 59.103 + x = htonl(x); 59.104 + err = marshal_bytes(io, &x, sizeof(x)); 59.105 + //dprintf("< err=%d\n", err); 59.106 + return err; 59.107 +} 59.108 + 59.109 +int unmarshal_uint32(IOStream *io, uint32_t *x){ 59.110 + int err = 0; 59.111 + //dprintf(">\n"); 59.112 + err = unmarshal_bytes(io, x, sizeof(*x)); 59.113 + *x = ntohl(*x); 59.114 + //dprintf("< err=%d x=%u\n", err, *x); 59.115 + return err; 59.116 +} 59.117 + 59.118 +int marshal_uint64(IOStream *io, uint64_t x){ 59.119 + int err; 59.120 + err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff)); 59.121 + if(err) goto exit; 59.122 + err = marshal_uint32(io, (uint32_t) ( x & 0xffffffff)); 59.123 + exit: 59.124 + return err; 59.125 +} 59.126 + 59.127 +int unmarshal_uint64(IOStream *io, uint64_t *x){ 59.128 + int err = 0; 59.129 + uint32_t hi, lo; 59.130 + err = unmarshal_uint32(io, &hi); 59.131 + if(err) goto exit; 59.132 + err = unmarshal_uint32(io, &lo); 59.133 + *x = (((uint64_t) hi) << 32) | lo; 59.134 + exit: 59.135 + return err; 59.136 +} 59.137 + 59.138 +int marshal_net16(IOStream *io, net16_t x){ 59.139 + return marshal_bytes(io, &x, sizeof(x)); 59.140 +} 59.141 + 59.142 +int unmarshal_net16(IOStream *io, net16_t *x){ 59.143 + int err = 0; 59.144 + err = unmarshal_bytes(io, x, sizeof(*x)); 59.145 + return err; 59.146 +} 59.147 + 59.148 +int marshal_net32(IOStream *io, net32_t x){ 59.149 + return marshal_bytes(io, &x, sizeof(x)); 59.150 +} 59.151 + 59.152 +int unmarshal_net32(IOStream *io, net32_t *x){ 59.153 + int err = 0; 59.154 + err = unmarshal_bytes(io, x, sizeof(*x)); 59.155 + return err; 59.156 +} 59.157 + 59.158 +int marshal_string(IOStream *io, char *s, uint32_t s_n){ 59.159 + int err; 59.160 + //dprintf("> s=%s\n", s); 59.161 + err = marshal_uint32(io, s_n); 59.162 + if(err) goto exit; 59.163 + err = marshal_bytes(io, s, s_n); 59.164 + exit: 59.165 + //dprintf("< err=%d\n", err); 59.166 + return err; 59.167 +} 59.168 + 59.169 +int unmarshal_string(IOStream *io, char *s, uint32_t s_n){ 59.170 + int err = 0, val_n = 0; 59.171 + //dprintf(">\n"); 59.172 + err = unmarshal_uint32(io, &val_n); 59.173 + if(err) goto exit; 59.174 + if(val_n >= s_n){ 59.175 + err = -EINVAL; 59.176 + goto exit; 59.177 + } 59.178 + err = unmarshal_bytes(io, s, val_n); 59.179 + if(err) goto exit; 59.180 + s[val_n] = '\0'; 59.181 + exit: 59.182 + //dprintf("< err=%d s=%s\n", err, s); 59.183 + return err; 59.184 +} 59.185 + 59.186 +int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){ 59.187 + int err = 0, val_n = 0; 59.188 + char *val = NULL; 59.189 + //dprintf(">\n"); 59.190 + err = unmarshal_uint32(io, &val_n); 59.191 + if(err) goto exit; 59.192 + val = allocate(val_n + 1); 59.193 + if(!val){ 59.194 + err = -ENOMEM; 59.195 + goto exit; 59.196 + } 59.197 + err = unmarshal_bytes(io, val, val_n); 59.198 + if(err) goto exit; 59.199 + val[val_n] = '\0'; 59.200 + exit: 59.201 + if(err){ 59.202 + if(val) deallocate(val); 59.203 + val = NULL; 59.204 + val_n = 0; 59.205 + } 59.206 + *s = val; 59.207 + if(s_n) *s_n = val_n; 59.208 + //dprintf("< err=%d s=%s\n", err, *s); 59.209 + return err; 59.210 +}
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 60.2 +++ b/tools/xfrd/marshal.h Tue Jul 06 17:27:27 2004 +0000 60.3 @@ -0,0 +1,42 @@ 60.4 +#ifndef _XUTIL_MARSHAL_H_ 60.5 +#define _XUTIL_MARSHAL_H_ 60.6 + 60.7 +#include "iostream.h" 60.8 + 60.9 +/** A 16-bit uint in network order, e.g. a port number. */ 60.10 +typedef uint16_t net16_t; 60.11 + 60.12 +/** A 32-bit uint in network order, e.g. an IP address. */ 60.13 +typedef uint32_t net32_t; 60.14 + 60.15 +extern int marshal_flush(IOStream *io); 60.16 + 60.17 +extern int marshal_bytes(IOStream *io, void *s, uint32_t s_n); 60.18 +extern int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n); 60.19 + 60.20 +extern int marshal_uint8(IOStream *io, uint8_t x); 60.21 +extern int unmarshal_uint8(IOStream *io, uint8_t *x); 60.22 + 60.23 +extern int marshal_uint16(IOStream *io, uint16_t x); 60.24 +extern int unmarshal_uint16(IOStream *io, uint16_t *x); 60.25 + 60.26 +extern int marshal_uint32(IOStream *io, uint32_t x); 60.27 +extern int unmarshal_uint32(IOStream *io, uint32_t *x); 60.28 + 60.29 +extern int marshal_int32(IOStream *io, int32_t x); 60.30 +extern int unmarshal_int32(IOStream *io, int32_t *x); 60.31 + 60.32 +extern int marshal_uint64(IOStream *io, uint64_t x); 60.33 +extern int unmarshal_uint64(IOStream *io, uint64_t *x); 60.34 + 60.35 +extern int marshal_net16(IOStream *io, net16_t x); 60.36 +extern int unmarshal_net16(IOStream *io, net16_t *x); 60.37 + 60.38 +extern int marshal_net32(IOStream *io, net32_t x); 60.39 +extern int unmarshal_net32(IOStream *io, net32_t *x); 60.40 + 60.41 +extern int marshal_string(IOStream *io, char *s, uint32_t s_n); 60.42 +extern int unmarshal_string(IOStream *io, char *s, uint32_t s_n); 60.43 +extern int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n); 60.44 + 60.45 +#endif /* ! _XUTIL_MARSHAL_H_ */
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 61.2 +++ b/tools/xfrd/select.c Tue Jul 06 17:27:27 2004 +0000 61.3 @@ -0,0 +1,50 @@ 61.4 +#include <stdlib.h> 61.5 +#include <errno.h> 61.6 +#include <unistd.h> 61.7 + 61.8 +#include "select.h" 61.9 + 61.10 +/** Zero all the file descriptor sets. 61.11 + * 61.12 + * @param set select set 61.13 + * @param fd file descriptor 61.14 + * @return 0 on success, -1 otherwise 61.15 + */ 61.16 +void SelectSet_zero(SelectSet *set){ 61.17 + set->n = 0; 61.18 + FD_ZERO(&set->rd); 61.19 + FD_ZERO(&set->wr); 61.20 + FD_ZERO(&set->er); 61.21 +} 61.22 + 61.23 +/** Add a file descriptor to the write set. 61.24 + * 61.25 + * @param set select set 61.26 + * @param fd file descriptor 61.27 + * @return 0 on success, -1 otherwise 61.28 + */ 61.29 +void SelectSet_add_read(SelectSet *set, int fd){ 61.30 + FD_SET(fd, &set->rd); 61.31 + if(fd > set->n) set->n = fd; 61.32 +} 61.33 + 61.34 +/** Add a file descriptor to the write set. 61.35 + * 61.36 + * @param set select set 61.37 + * @param fd file descriptor 61.38 + * @return 0 on success, -1 otherwise 61.39 + */ 61.40 +void SelectSet_add_write(SelectSet *set, int fd){ 61.41 + FD_SET(fd, &set->wr); 61.42 + if(fd > set->n) set->n = fd; 61.43 +} 61.44 + 61.45 +/** Select on file descriptors. 61.46 + * 61.47 + * @param set select set 61.48 + * @param timeout timeout (may be NULL for no timeout) 61.49 + * @return 0 on success, -1 otherwise 61.50 + */ 61.51 +int SelectSet_select(SelectSet *set, struct timeval *timeout){ 61.52 + return select(set->n+1, &set->rd, &set->wr, &set->er, timeout); 61.53 +}
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/tools/xfrd/select.h Tue Jul 06 17:27:27 2004 +0000 62.3 @@ -0,0 +1,16 @@ 62.4 +#ifndef _XFRD_SELECT_H_ 62.5 +#define _XFRD_SELECT_H_ 62.6 + 62.7 +/** Set of file descriptors for select. 62.8 + */ 62.9 +typedef struct SelectSet { 62.10 + int n; 62.11 + fd_set rd, wr, er; 62.12 +} SelectSet; 62.13 + 62.14 +extern void SelectSet_zero(SelectSet *set); 62.15 +extern void SelectSet_add_read(SelectSet *set, int fd); 62.16 +extern void SelectSet_add_write(SelectSet *set, int fd); 62.17 +extern int SelectSet_select(SelectSet *set, struct timeval *timeout); 62.18 + 62.19 +#endif /* ! _XFRD_SELECT_H_ */
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 63.2 +++ b/tools/xfrd/sxpr.c Tue Jul 06 17:27:27 2004 +0000 63.3 @@ -0,0 +1,950 @@ 63.4 +/* 63.5 + * 63.6 + * This library is free software; you can redistribute it and/or modify 63.7 + * it under the terms of the GNU Lesser General Public License as 63.8 + * published by the Free Software Foundation; either version 2.1 of the 63.9 + * License, or (at your option) any later version. This library is 63.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 63.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 63.12 + * FITNESS FOR A PARTICULAR PURPOSE. 63.13 + * See the GNU Lesser General Public License for more details. 63.14 + * 63.15 + * You should have received a copy of the GNU Lesser General Public License 63.16 + * along with this library; if not, write to the Free Software Foundation, 63.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 63.18 + */ 63.19 + 63.20 +#include <stdarg.h> 63.21 +#include "sys_string.h" 63.22 +#include "lexis.h" 63.23 +#include "sys_net.h" 63.24 +#include "hash_table.h" 63.25 +#include "sxpr.h" 63.26 + 63.27 +#include <errno.h> 63.28 +#undef free 63.29 + 63.30 +/** @file 63.31 + * General representation of sxprs. 63.32 + * Includes print, equal, and free functions for the sxpr types. 63.33 + * 63.34 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional. 63.35 + * When a function returning an sxpr cannot allocate memory we return ONOMEM. 63.36 + * 63.37 + */ 63.38 + 63.39 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags); 63.40 +static int atom_equal(Sxpr x, Sxpr y); 63.41 +static void atom_free(Sxpr obj); 63.42 + 63.43 +static int string_print(IOStream *io, Sxpr obj, unsigned flags); 63.44 +static int string_equal(Sxpr x, Sxpr y); 63.45 +static void string_free(Sxpr obj); 63.46 + 63.47 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags); 63.48 +static int cons_equal(Sxpr x, Sxpr y); 63.49 +static void cons_free(Sxpr obj); 63.50 + 63.51 +static int null_print(IOStream *io, Sxpr obj, unsigned flags); 63.52 +static int none_print(IOStream *io, Sxpr obj, unsigned flags); 63.53 +static int int_print(IOStream *io, Sxpr obj, unsigned flags); 63.54 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags); 63.55 + 63.56 +/** Type definitions. */ 63.57 +static SxprType types[1024] = { 63.58 + [T_NONE] { type: T_NONE, name: "none", print: none_print }, 63.59 + [T_NULL] { type: T_NULL, name: "null", print: null_print }, 63.60 + [T_UINT] { type: T_UINT, name: "int", print: int_print, }, 63.61 + [T_BOOL] { type: T_BOOL, name: "bool", print: bool_print, }, 63.62 + [T_ATOM] { type: T_ATOM, name: "atom", print: atom_print, 63.63 + pointer: TRUE, 63.64 + free: atom_free, 63.65 + equal: atom_equal, 63.66 + }, 63.67 + [T_STRING] { type: T_STRING, name: "string", print: string_print, 63.68 + pointer: TRUE, 63.69 + free: string_free, 63.70 + equal: string_equal, 63.71 + }, 63.72 + [T_CONS] { type: T_CONS, name: "cons", print: cons_print, 63.73 + pointer: TRUE, 63.74 + free: cons_free, 63.75 + equal: cons_equal, 63.76 + }, 63.77 +}; 63.78 + 63.79 +/** Number of entries in the types array. */ 63.80 +static int type_sup = sizeof(types)/sizeof(types[0]); 63.81 + 63.82 +/** Get the type definition for a given type code. 63.83 + * 63.84 + * @param ty type code 63.85 + * @return type definition or null 63.86 + */ 63.87 +SxprType *get_sxpr_type(int ty){ 63.88 + if(0 <= ty && ty < type_sup){ 63.89 + return types+ty; 63.90 + } 63.91 + return NULL; 63.92 +} 63.93 + 63.94 +/** The default print function. 63.95 + * 63.96 + * @param io stream to print to 63.97 + * @param x sxpr to print 63.98 + * @param flags print flags 63.99 + * @return number of bytes written on success 63.100 + */ 63.101 +int default_print(IOStream *io, Sxpr x, unsigned flags){ 63.102 + return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x)); 63.103 +} 63.104 + 63.105 +/** The default equal function. 63.106 + * Uses eq(). 63.107 + * 63.108 + * @param x sxpr to compare 63.109 + * @param y sxpr to compare 63.110 + * @return 1 if equal, 0 otherwise 63.111 + */ 63.112 +int default_equal(Sxpr x, Sxpr y){ 63.113 + return eq(x, y); 63.114 +} 63.115 + 63.116 +/** General sxpr print function. 63.117 + * Prints an sxpr on a stream using the print function for the sxpr type. 63.118 + * Printing is controlled by flags from the PrintFlags enum. 63.119 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr 63.120 + * (for debugging). 63.121 + * 63.122 + * @param io stream to print to 63.123 + * @param x sxpr to print 63.124 + * @param flags print flags 63.125 + * @return number of bytes written 63.126 + */ 63.127 +int objprint(IOStream *io, Sxpr x, unsigned flags){ 63.128 + SxprType *def = get_sxpr_type(get_type(x)); 63.129 + ObjPrintFn *print_fn = (def && def->print ? def->print : default_print); 63.130 + int k = 0; 63.131 + if(!io) return k; 63.132 + if(flags & PRINT_TYPE){ 63.133 + k += IOStream_print(io, "%s:", def->name); 63.134 + } 63.135 + k += print_fn(io, x, flags); 63.136 + return k; 63.137 +} 63.138 + 63.139 +/** General sxpr free function. 63.140 + * Frees an sxpr using the free function for its type. 63.141 + * Free functions must recursively free any subsxprs. 63.142 + * If no function is defined then the default is to 63.143 + * free sxprs whose type has pointer true. 63.144 + * Sxprs must not be used after freeing. 63.145 + * 63.146 + * @param x sxpr to free 63.147 + */ 63.148 +void objfree(Sxpr x){ 63.149 + SxprType *def = get_sxpr_type(get_type(x)); 63.150 + 63.151 + if(def){ 63.152 + if(def->free){ 63.153 + def->free(x); 63.154 + } else if (def->pointer){ 63.155 + hfree(x); 63.156 + } 63.157 + } 63.158 +} 63.159 + 63.160 +/** General sxpr equality function. 63.161 + * Compares x and y using the equal function for x. 63.162 + * Uses default_equal() if x has no equal function. 63.163 + * 63.164 + * @param x sxpr to compare 63.165 + * @param y sxpr to compare 63.166 + * @return 1 if equal, 0 otherwise 63.167 + */ 63.168 +int objequal(Sxpr x, Sxpr y){ 63.169 + SxprType *def = get_sxpr_type(get_type(x)); 63.170 + ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal); 63.171 + return equal_fn(x, y); 63.172 +} 63.173 + 63.174 +/** Search for a key in an alist. 63.175 + * An alist is a list of conses, where the cars 63.176 + * of the conses are the keys. Compares keys using equality. 63.177 + * 63.178 + * @param k key 63.179 + * @param l alist to search 63.180 + * @return first element of l with car k, or ONULL 63.181 + */ 63.182 +Sxpr assoc(Sxpr k, Sxpr l){ 63.183 + for( ; CONSP(l) ; l = CDR(l)){ 63.184 + Sxpr x = CAR(l); 63.185 + if(CONSP(x) && objequal(k, CAR(x))){ 63.186 + return x; 63.187 + } 63.188 + } 63.189 + return ONULL; 63.190 +} 63.191 + 63.192 +/** Search for a key in an alist. 63.193 + * An alist is a list of conses, where the cars 63.194 + * of the conses are the keys. Compares keys using eq. 63.195 + * 63.196 + * @param k key 63.197 + * @param l alist to search 63.198 + * @return first element of l with car k, or ONULL 63.199 + */ 63.200 +Sxpr assocq(Sxpr k, Sxpr l){ 63.201 + for( ; CONSP(l); l = CDR(l)){ 63.202 + Sxpr x = CAR(l); 63.203 + if(CONSP(x) && eq(k, CAR(x))){ 63.204 + return x; 63.205 + } 63.206 + } 63.207 + return ONULL; 63.208 +} 63.209 + 63.210 +/** Add a new key and value to an alist. 63.211 + * 63.212 + * @param k key 63.213 + * @param l value 63.214 + * @param l alist 63.215 + * @return l with the new cell added to the front 63.216 + */ 63.217 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){ 63.218 + Sxpr x, y; 63.219 + x = cons_new(k, v); 63.220 + if(NOMEMP(x)) return x; 63.221 + y = cons_new(x, l); 63.222 + if(NOMEMP(y)) cons_free_cells(x); 63.223 + return y; 63.224 +} 63.225 + 63.226 +/** Test if a list contains an element. 63.227 + * Uses sxpr equality. 63.228 + * 63.229 + * @param l list 63.230 + * @param x element to look for 63.231 + * @return a tail of l with x as car, or ONULL 63.232 + */ 63.233 +Sxpr cons_member(Sxpr l, Sxpr x){ 63.234 + for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){} 63.235 + return l; 63.236 +} 63.237 + 63.238 +/** Test if a list contains an element satisfying a test. 63.239 + * The test function is called with v and an element of the list. 63.240 + * 63.241 + * @param l list 63.242 + * @param test_fn test function to use 63.243 + * @param v value for first argument to the test 63.244 + * @return a tail of l with car satisfying the test, or 0 63.245 + */ 63.246 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 63.247 + for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ } 63.248 + return l; 63.249 +} 63.250 + 63.251 +/** Test if the elements of list 't' are a subset of the elements 63.252 + * of list 's'. Element order is not significant. 63.253 + * 63.254 + * @param s element list to check subset of 63.255 + * @param t element list to check if is a subset 63.256 + * @return 1 if is a subset, 0 otherwise 63.257 + */ 63.258 +int cons_subset(Sxpr s, Sxpr t){ 63.259 + for( ; CONSP(t); t = CDR(t)){ 63.260 + if(!CONSP(cons_member(s, CAR(t)))){ 63.261 + return 0; 63.262 + } 63.263 + } 63.264 + return 1; 63.265 +} 63.266 + 63.267 +/** Test if two lists have equal sets of elements. 63.268 + * Element order is not significant. 63.269 + * 63.270 + * @param s list to check 63.271 + * @param t list to check 63.272 + * @return 1 if equal, 0 otherwise 63.273 + */ 63.274 +int cons_set_equal(Sxpr s, Sxpr t){ 63.275 + return cons_subset(s, t) && cons_subset(t, s); 63.276 +} 63.277 + 63.278 +#ifdef USE_GC 63.279 +/*============================================================================*/ 63.280 +/* The functions inside this ifdef are only safe if GC is used. 63.281 + * Otherwise they may leak memory. 63.282 + */ 63.283 + 63.284 +/** Remove an element from a list (GC only). 63.285 + * Uses sxpr equality and removes all instances, even 63.286 + * if there are more than one. 63.287 + * 63.288 + * @param l list to remove elements from 63.289 + * @param x element to remove 63.290 + * @return modified input list 63.291 + */ 63.292 +Sxpr cons_remove(Sxpr l, Sxpr x){ 63.293 + return cons_remove_if(l, eq, x); 63.294 +} 63.295 + 63.296 +/** Remove elements satisfying a test (GC only). 63.297 + * The test function is called with v and an element of the set. 63.298 + * 63.299 + * @param l list to remove elements from 63.300 + * @param test_fn function to use to decide if an element should be removed 63.301 + * @return modified input list 63.302 + */ 63.303 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){ 63.304 + Sxpr prev = ONULL, elt, next; 63.305 + 63.306 + for(elt = l; CONSP(elt); elt = next){ 63.307 + next = CDR(elt); 63.308 + if(test_fn(v, CAR(elt))){ 63.309 + if(NULLP(prev)){ 63.310 + l = next; 63.311 + } else { 63.312 + CDR(prev) = next; 63.313 + } 63.314 + } 63.315 + } 63.316 + return l; 63.317 +} 63.318 + 63.319 +/** Set the value for a key in an alist (GC only). 63.320 + * If the key is present, changes the value, otherwise 63.321 + * adds a new cell. 63.322 + * 63.323 + * @param k key 63.324 + * @param v value 63.325 + * @param l alist 63.326 + * @return modified or extended list 63.327 + */ 63.328 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){ 63.329 + Sxpr e = assoc(k, l); 63.330 + if(NULLP(e)){ 63.331 + l = acons(k, v, l); 63.332 + } else { 63.333 + CAR(CDR(e)) = v; 63.334 + } 63.335 + return l; 63.336 +} 63.337 +/*============================================================================*/ 63.338 +#endif /* USE_GC */ 63.339 + 63.340 +/** Create a new atom with the given name. 63.341 + * 63.342 + * @param name the name 63.343 + * @return new atom 63.344 + */ 63.345 +Sxpr atom_new(char *name){ 63.346 + Sxpr n, obj = ONOMEM; 63.347 + 63.348 + n = string_new(name); 63.349 + if(NOMEMP(n)) goto exit; 63.350 + obj = HALLOC(ObjAtom, T_ATOM); 63.351 + if(NOMEMP(obj)) goto exit; 63.352 + OBJ_ATOM(obj)->name = n; 63.353 + exit: 63.354 + return obj; 63.355 +} 63.356 + 63.357 +/** Free an atom. 63.358 + * 63.359 + * @param obj to free 63.360 + */ 63.361 +void atom_free(Sxpr obj){ 63.362 + // Interned atoms are shared, so do not free. 63.363 + if(OBJ_ATOM(obj)->interned) return; 63.364 + objfree(OBJ_ATOM(obj)->name); 63.365 + hfree(obj); 63.366 +} 63.367 + 63.368 +/** Print an atom. Prints the atom name. 63.369 + * 63.370 + * @param io stream to print to 63.371 + * @param obj to print 63.372 + * @param flags print flags 63.373 + * @return number of bytes printed 63.374 + */ 63.375 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){ 63.376 + //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW)); 63.377 + return string_print(io, OBJ_ATOM(obj)->name, flags); 63.378 +} 63.379 + 63.380 +/** Atom equality. 63.381 + * 63.382 + * @param x to compare 63.383 + * @param y to compare 63.384 + * @return 1 if equal, 0 otherwise 63.385 + */ 63.386 +int atom_equal(Sxpr x, Sxpr y){ 63.387 + int ok; 63.388 + ok = eq(x, y); 63.389 + if(ok) goto exit; 63.390 + ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name); 63.391 + if(ok) goto exit; 63.392 + ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y); 63.393 + exit: 63.394 + return ok; 63.395 +} 63.396 + 63.397 +/** Get the name of an atom. 63.398 + * 63.399 + * @param obj atom 63.400 + * @return name 63.401 + */ 63.402 +char * atom_name(Sxpr obj){ 63.403 + return string_string(OBJ_ATOM(obj)->name); 63.404 +} 63.405 + 63.406 +/** Get the C string from a string sxpr. 63.407 + * 63.408 + * @param obj string sxpr 63.409 + * @return string 63.410 + */ 63.411 +char * string_string(Sxpr obj){ 63.412 + return OBJ_STRING(obj); 63.413 +} 63.414 + 63.415 +/** Get the length of a string. 63.416 + * 63.417 + * @param obj string 63.418 + * @return length 63.419 + */ 63.420 +int string_length(Sxpr obj){ 63.421 + return strlen(OBJ_STRING(obj)); 63.422 +} 63.423 + 63.424 +/** Create a new string. The input string is copied, 63.425 + * and must be null-terminated. 63.426 + * 63.427 + * @param s characters to put in the string 63.428 + * @return new sxpr 63.429 + */ 63.430 +Sxpr string_new(char *s){ 63.431 + int n = (s ? strlen(s) : 0); 63.432 + Sxpr obj; 63.433 + obj = halloc(n+1, T_STRING); 63.434 + if(!NOMEMP(obj)){ 63.435 + char *str = OBJ_STRING(obj); 63.436 + strncpy(str, s, n); 63.437 + str[n] = '\0'; 63.438 + } 63.439 + return obj; 63.440 +} 63.441 + 63.442 +/** Free a string. 63.443 + * 63.444 + * @param obj to free 63.445 + */ 63.446 +void string_free(Sxpr obj){ 63.447 + hfree(obj); 63.448 +} 63.449 + 63.450 +/** Determine if a string needs escapes when printed 63.451 + * using the given flags. 63.452 + * 63.453 + * @param str string to check 63.454 + * @param flags print flags 63.455 + * @return 1 if needs escapes, 0 otherwise 63.456 + */ 63.457 +int needs_escapes(char *str, unsigned flags){ 63.458 + char *c; 63.459 + int val = 0; 63.460 + 63.461 + if(str){ 63.462 + for(c=str; *c; c++){ 63.463 + if(in_alpha_class(*c)) continue; 63.464 + if(in_decimal_digit_class(*c)) continue; 63.465 + if(in_class(*c, "/._+:@~-")) continue; 63.466 + val = 1; 63.467 + break; 63.468 + } 63.469 + } 63.470 + //printf("\n> val=%d str=|%s|\n", val, str); 63.471 + return val; 63.472 +} 63.473 + 63.474 +/** Print a string to a stream, with escapes if necessary. 63.475 + * 63.476 + * @param io stream to print to 63.477 + * @param str string 63.478 + * @param flags print flags 63.479 + * @return number of bytes written 63.480 + */ 63.481 +int _string_print(IOStream *io, char *str, unsigned flags){ 63.482 + int k = 0; 63.483 + if((flags & PRINT_RAW) || !needs_escapes(str, flags)){ 63.484 + k += IOStream_print(io, str); 63.485 + } else { 63.486 + k += IOStream_print(io, "\""); 63.487 + if(str){ 63.488 + char *s; 63.489 + for(s = str; *s; s++){ 63.490 + if(*s < ' ' || *s >= 127 ){ 63.491 + switch(*s){ 63.492 + case '\a': k += IOStream_print(io, "\\a"); break; 63.493 + case '\b': k += IOStream_print(io, "\\b"); break; 63.494 + case '\f': k += IOStream_print(io, "\\f"); break; 63.495 + case '\n': k += IOStream_print(io, "\\n"); break; 63.496 + case '\r': k += IOStream_print(io, "\\r"); break; 63.497 + case '\t': k += IOStream_print(io, "\\t"); break; 63.498 + case '\v': k += IOStream_print(io, "\\v"); break; 63.499 + default: 63.500 + // Octal escape; 63.501 + k += IOStream_print(io, "\\%o", *s); 63.502 + break; 63.503 + } 63.504 + } else if(*s == c_double_quote || 63.505 + *s == c_single_quote || 63.506 + *s == c_escape){ 63.507 + k += IOStream_print(io, "\\%c", *s); 63.508 + } else { 63.509 + k+= IOStream_print(io, "%c", *s); 63.510 + } 63.511 + } 63.512 + } 63.513 + k += IOStream_print(io, "\""); 63.514 + } 63.515 + return k; 63.516 +} 63.517 + 63.518 +/** Print a string to a stream, with escapes if necessary. 63.519 + * 63.520 + * @param io stream to print to 63.521 + * @param obj string 63.522 + * @param flags print flags 63.523 + * @return number of bytes written 63.524 + */ 63.525 +int string_print(IOStream *io, Sxpr obj, unsigned flags){ 63.526 + return _string_print(io, OBJ_STRING(obj), flags); 63.527 +} 63.528 + 63.529 +/** Compare an sxpr with a string for equality. 63.530 + * 63.531 + * @param x string to compare with 63.532 + * @param y sxpr to compare 63.533 + * @return 1 if equal, 0 otherwise 63.534 + */ 63.535 +int string_equal(Sxpr x, Sxpr y){ 63.536 + int ok = 0; 63.537 + ok = eq(x,y); 63.538 + if(ok) goto exit; 63.539 + ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y)); 63.540 + if(ok) goto exit; 63.541 + ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y)); 63.542 + exit: 63.543 + return ok; 63.544 +} 63.545 + 63.546 +/** Create a new cons cell. 63.547 + * The cell is ONOMEM if either argument is. 63.548 + * 63.549 + * @param car sxpr for the car 63.550 + * @param cdr sxpr for the cdr 63.551 + * @return new cons 63.552 + */ 63.553 +Sxpr cons_new(Sxpr car, Sxpr cdr){ 63.554 + Sxpr obj; 63.555 + if(NOMEMP(car) || NOMEMP(cdr)){ 63.556 + obj = ONOMEM; 63.557 + } else { 63.558 + obj = HALLOC(ObjCons, T_CONS); 63.559 + if(!NOMEMP(obj)){ 63.560 + ObjCons *z = OBJ_CONS(obj); 63.561 + z->car = car; 63.562 + z->cdr = cdr; 63.563 + } 63.564 + } 63.565 + return obj; 63.566 +} 63.567 + 63.568 +/** Push a new element onto a list. 63.569 + * 63.570 + * @param list list to add to 63.571 + * @param elt element to add 63.572 + * @return 0 if successful, error code otherwise 63.573 + */ 63.574 +int cons_push(Sxpr *list, Sxpr elt){ 63.575 + Sxpr l; 63.576 + l = cons_new(elt, *list); 63.577 + if(NOMEMP(l)) return -ENOMEM; 63.578 + *list = l; 63.579 + return 0; 63.580 +} 63.581 + 63.582 +/** Free a cons. Recursively frees the car and cdr. 63.583 + * 63.584 + * @param obj to free 63.585 + */ 63.586 +void cons_free(Sxpr obj){ 63.587 + Sxpr next; 63.588 + for(; CONSP(obj); obj = next){ 63.589 + next = CDR(obj); 63.590 + objfree(CAR(obj)); 63.591 + hfree(obj); 63.592 + } 63.593 + if(!NULLP(obj)){ 63.594 + objfree(obj); 63.595 + } 63.596 +} 63.597 + 63.598 +/** Free a cons and its cdr cells, but not the car sxprs. 63.599 + * Does nothing if called on something that is not a cons. 63.600 + * 63.601 + * @param obj to free 63.602 + */ 63.603 +void cons_free_cells(Sxpr obj){ 63.604 + Sxpr next; 63.605 + for(; CONSP(obj); obj = next){ 63.606 + next = CDR(obj); 63.607 + hfree(obj); 63.608 + } 63.609 +} 63.610 + 63.611 +/** Print a cons. 63.612 + * Prints the cons in list format if the cdrs are conses. 63.613 + * uses pair (dot) format if the last cdr is not a cons (or null). 63.614 + * 63.615 + * @param io stream to print to 63.616 + * @param obj to print 63.617 + * @param flags print flags 63.618 + * @return number of bytes written 63.619 + */ 63.620 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){ 63.621 + int first = 1; 63.622 + int k = 0; 63.623 + k += IOStream_print(io, "("); 63.624 + for( ; CONSP(obj) ; obj = CDR(obj)){ 63.625 + if(first){ 63.626 + first = 0; 63.627 + } else { 63.628 + k += IOStream_print(io, " "); 63.629 + } 63.630 + k += objprint(io, CAR(obj), flags); 63.631 + } 63.632 + if(!NULLP(obj)){ 63.633 + k += IOStream_print(io, " . "); 63.634 + k += objprint(io, obj, flags); 63.635 + } 63.636 + k += IOStream_print(io, ")"); 63.637 + return (IOStream_error(io) ? -1 : k); 63.638 +} 63.639 + 63.640 +/** Compare a cons with another sxpr for equality. 63.641 + * If y is a cons, compares the cars and cdrs recursively. 63.642 + * 63.643 + * @param x cons to compare 63.644 + * @param y sxpr to compare 63.645 + * @return 1 if equal, 0 otherwise 63.646 + */ 63.647 +int cons_equal(Sxpr x, Sxpr y){ 63.648 + return CONSP(y) && 63.649 + objequal(CAR(x), CAR(y)) && 63.650 + objequal(CDR(x), CDR(y)); 63.651 +} 63.652 + 63.653 +/** Return the length of a cons list. 63.654 + * 63.655 + * @param obj list 63.656 + * @return length 63.657 + */ 63.658 +int cons_length(Sxpr obj){ 63.659 + int count = 0; 63.660 + for( ; CONSP(obj); obj = CDR(obj)){ 63.661 + count++; 63.662 + } 63.663 + return count; 63.664 +} 63.665 + 63.666 +/** Destructively reverse a cons list in-place. 63.667 + * If the argument is not a cons it is returned unchanged. 63.668 + * 63.669 + * @param l to reverse 63.670 + * @return reversed list 63.671 + */ 63.672 +Sxpr nrev(Sxpr l){ 63.673 + if(CONSP(l)){ 63.674 + // Iterate down the cells in the list making the cdr of 63.675 + // each cell point to the previous cell. The last cell 63.676 + // is the head of the reversed list. 63.677 + Sxpr prev = ONULL; 63.678 + Sxpr cell = l; 63.679 + Sxpr next; 63.680 + 63.681 + while(1){ 63.682 + next = CDR(cell); 63.683 + CDR(cell) = prev; 63.684 + if(!CONSP(next)) break; 63.685 + prev = cell; 63.686 + cell = next; 63.687 + } 63.688 + l = cell; 63.689 + } 63.690 + return l; 63.691 +} 63.692 + 63.693 +/** Print the null sxpr. 63.694 + * 63.695 + * @param io stream to print to 63.696 + * @param obj to print 63.697 + * @param flags print flags 63.698 + * @return number of bytes written 63.699 + */ 63.700 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){ 63.701 + return IOStream_print(io, "()"); 63.702 +} 63.703 + 63.704 +/** Print the `unspecified' sxpr none. 63.705 + * 63.706 + * @param io stream to print to 63.707 + * @param obj to print 63.708 + * @param flags print flags 63.709 + * @return number of bytes written 63.710 + */ 63.711 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){ 63.712 + return IOStream_print(io, "<none>"); 63.713 +} 63.714 + 63.715 +/** Print an integer. 63.716 + * 63.717 + * @param io stream to print to 63.718 + * @param obj to print 63.719 + * @param flags print flags 63.720 + * @return number of bytes written 63.721 + */ 63.722 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){ 63.723 + return IOStream_print(io, "%d", OBJ_INT(obj)); 63.724 +} 63.725 + 63.726 +/** Print a boolean. 63.727 + * 63.728 + * @param io stream to print to 63.729 + * @param obj to print 63.730 + * @param flags print flags 63.731 + * @return number of bytes written 63.732 + */ 63.733 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){ 63.734 + return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false)); 63.735 +} 63.736 + 63.737 +int sxprp(Sxpr obj, Sxpr name){ 63.738 + return CONSP(obj) && objequal(CAR(obj), name); 63.739 +} 63.740 + 63.741 +/** Get the name of an element. 63.742 + * 63.743 + * @param obj element 63.744 + * @return name 63.745 + */ 63.746 +Sxpr sxpr_name(Sxpr obj){ 63.747 + Sxpr val = ONONE; 63.748 + if(CONSP(obj)){ 63.749 + val = CAR(obj); 63.750 + } else if(STRINGP(obj) || ATOMP(obj)){ 63.751 + val = obj; 63.752 + } 63.753 + return val; 63.754 +} 63.755 + 63.756 +int sxpr_is(Sxpr obj, char *s){ 63.757 + if(ATOMP(obj)) return !strcmp(atom_name(obj), s); 63.758 + if(STRINGP(obj)) return !strcmp(string_string(obj), s); 63.759 + return 0; 63.760 +} 63.761 + 63.762 +int sxpr_elementp(Sxpr obj, Sxpr name){ 63.763 + int ok = 0; 63.764 + ok = CONSP(obj) && objequal(CAR(obj), name); 63.765 + return ok; 63.766 +} 63.767 + 63.768 +/** Get the attributes of an sxpr. 63.769 + * 63.770 + * @param obj sxpr 63.771 + * @return attributes 63.772 + */ 63.773 +Sxpr sxpr_attributes(Sxpr obj){ 63.774 + Sxpr val = ONULL; 63.775 + if(CONSP(obj)){ 63.776 + obj = CDR(obj); 63.777 + if(CONSP(obj)){ 63.778 + obj = CAR(obj); 63.779 + if(sxprp(obj, intern("@"))){ 63.780 + val = CDR(obj); 63.781 + } 63.782 + } 63.783 + } 63.784 + return val; 63.785 +} 63.786 + 63.787 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){ 63.788 + Sxpr val = ONONE; 63.789 + val = assoc(sxpr_attributes(obj), key); 63.790 + if(CONSP(val) && CONSP(CDR(val))){ 63.791 + val = CADR(def); 63.792 + } else { 63.793 + val = def; 63.794 + } 63.795 + return val; 63.796 +} 63.797 + 63.798 +/** Get the children of an sxpr. 63.799 + * 63.800 + * @param obj sxpr 63.801 + * @return children 63.802 + */ 63.803 +Sxpr sxpr_children(Sxpr obj){ 63.804 + Sxpr val = ONULL; 63.805 + if(CONSP(obj)){ 63.806 + val = CDR(obj); 63.807 + if(CONSP(val) && sxprp(CAR(val), intern("@"))){ 63.808 + val = CDR(val); 63.809 + } 63.810 + } 63.811 + return val; 63.812 +} 63.813 + 63.814 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){ 63.815 + Sxpr val = ONONE; 63.816 + Sxpr l; 63.817 + for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){ 63.818 + if(sxprp(CAR(l), name)){ 63.819 + val = CAR(l); 63.820 + break; 63.821 + } 63.822 + } 63.823 + if(NONEP(val)) val = def; 63.824 + return val; 63.825 +} 63.826 + 63.827 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){ 63.828 + Sxpr val = ONONE; 63.829 + Sxpr l = sxpr_children(obj); 63.830 + if(CONSP(l)){ 63.831 + val = CAR(l); 63.832 + } else { 63.833 + val = def; 63.834 + } 63.835 + return val; 63.836 +} 63.837 + 63.838 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){ 63.839 + Sxpr val = def; 63.840 + Sxpr l; 63.841 + int i; 63.842 + for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){ 63.843 + if(i == n){ 63.844 + val = CAR(l); 63.845 + break; 63.846 + } 63.847 + } 63.848 + return val; 63.849 +} 63.850 + 63.851 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){ 63.852 + Sxpr val = ONONE; 63.853 + val = sxpr_child(obj, name, ONONE); 63.854 + if(NONEP(val)){ 63.855 + val = def; 63.856 + } else { 63.857 + val = sxpr_child0(val, def); 63.858 + } 63.859 + return val; 63.860 +} 63.861 + 63.862 +/** Table of interned symbols. Indexed by symbol name. */ 63.863 +static HashTable *symbols = NULL; 63.864 + 63.865 +/** Hash function for entries in the symbol table. 63.866 + * 63.867 + * @param key to hash 63.868 + * @return hashcode 63.869 + */ 63.870 +static Hashcode sym_hash_fn(void *key){ 63.871 + return hash_string((char*)key); 63.872 +} 63.873 + 63.874 +/** Key equality function for the symbol table. 63.875 + * 63.876 + * @param x to compare 63.877 + * @param y to compare 63.878 + * @return 1 if equal, 0 otherwise 63.879 + */ 63.880 +static int sym_equal_fn(void *x, void *y){ 63.881 + return !strcmp((char*)x, (char*)y); 63.882 +} 63.883 + 63.884 +/** Entry free function for the symbol table. 63.885 + * 63.886 + * @param table the entry is in 63.887 + * @param entry being freed 63.888 + */ 63.889 +static void sym_free_fn(HashTable *table, HTEntry *entry){ 63.890 + if(entry){ 63.891 + objfree(((ObjAtom*)entry->value)->name); 63.892 + HTEntry_free(entry); 63.893 + } 63.894 +} 63.895 + 63.896 +/** Initialize the symbol table. 63.897 + * 63.898 + * @return 0 on sucess, error code otherwise 63.899 + */ 63.900 +static int init_symbols(void){ 63.901 + symbols = HashTable_new(100); 63.902 + if(symbols){ 63.903 + symbols->key_hash_fn = sym_hash_fn; 63.904 + symbols->key_equal_fn = sym_equal_fn; 63.905 + symbols->entry_free_fn = sym_free_fn; 63.906 + return 0; 63.907 + } 63.908 + return -1; 63.909 +} 63.910 + 63.911 +/** Cleanup the symbol table. Frees the table and all its symbols. 63.912 + */ 63.913 +void cleanup_symbols(void){ 63.914 + HashTable_free(symbols); 63.915 + symbols = NULL; 63.916 +} 63.917 + 63.918 +/** Get the interned symbol with the given name. 63.919 + * No new symbol is created. 63.920 + * 63.921 + * @return symbol or null 63.922 + */ 63.923 +Sxpr get_symbol(char *sym){ 63.924 + HTEntry *entry; 63.925 + if(!symbols){ 63.926 + if(init_symbols()) return ONOMEM; 63.927 + return ONULL; 63.928 + } 63.929 + entry = HashTable_get_entry(symbols, sym); 63.930 + if(entry){ 63.931 + return OBJP(T_ATOM, entry->value); 63.932 + } else { 63.933 + return ONULL; 63.934 + } 63.935 +} 63.936 + 63.937 +/** Get the interned symbol with the given name. 63.938 + * Creates a new symbol if necessary. 63.939 + * 63.940 + * @return symbol 63.941 + */ 63.942 +Sxpr intern(char *sym){ 63.943 + Sxpr symbol = get_symbol(sym); 63.944 + if(NULLP(symbol)){ 63.945 + if(!symbols) return ONOMEM; 63.946 + symbol = atom_new(sym); 63.947 + if(!NOMEMP(symbol)){ 63.948 + OBJ_ATOM(symbol)->interned = TRUE; 63.949 + HashTable_add(symbols, atom_name(symbol), get_ptr(symbol)); 63.950 + } 63.951 + } 63.952 + return symbol; 63.953 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 64.2 +++ b/tools/xfrd/sxpr.h Tue Jul 06 17:27:27 2004 +0000 64.3 @@ -0,0 +1,414 @@ 64.4 +/* 64.5 + * 64.6 + * This library is free software; you can redistribute it and/or modify 64.7 + * it under the terms of the GNU Lesser General Public License as 64.8 + * published by the Free Software Foundation; either version 2.1 of the 64.9 + * License, or (at your option) any later version. This library is 64.10 + * distributed in the hope that it will be useful, but WITHOUT ANY 64.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or 64.12 + * FITNESS FOR A PARTICULAR PURPOSE. 64.13 + * See the GNU Lesser General Public License for more details. 64.14 + * 64.15 + * You should have received a copy of the GNU Lesser General Public License 64.16 + * along with this library; if not, write to the Free Software Foundation, 64.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 64.18 + */ 64.19 +#ifndef _XUTIL_SXPR_H_ 64.20 +#define _XUTIL_SXPR_H_ 64.21 + 64.22 +#include <stdint.h> 64.23 + 64.24 +#include "hash_table.h" 64.25 +#include "iostream.h" 64.26 +#include "allocate.h" 64.27 + 64.28 +/** @file 64.29 + * Definitions for rules and sxprs. 64.30 + */ 64.31 + 64.32 +#ifndef NULL 64.33 +#define NULL 0 64.34 +#endif 64.35 + 64.36 +#ifndef TRUE 64.37 +#define TRUE 1 64.38 +#endif 64.39 + 64.40 +#ifndef FALSE 64.41 +#define FALSE 0 64.42 +#endif 64.43 + 64.44 +/** Sxpr type. */ 64.45 +typedef int16_t TypeCode; 64.46 + 64.47 +/** A typed sxpr handle.*/ 64.48 +typedef struct Sxpr { 64.49 + /** Sxpr type. */ 64.50 + TypeCode type; 64.51 + union { 64.52 + /** Sxpr value. */ 64.53 + unsigned long ul; 64.54 + /** Pointer. */ 64.55 + void *ptr; 64.56 + } v; 64.57 +} Sxpr; 64.58 + 64.59 +/** Sxpr type to indicate out of memory. */ 64.60 +#define T_NOMEM ((TypeCode)-1) 64.61 +/** The 'unspecified' sxpr. */ 64.62 +#define T_NONE ((TypeCode)0) 64.63 +/** The empty list. */ 64.64 +#define T_NULL ((TypeCode)1) 64.65 +/** Unsigned integer. */ 64.66 +#define T_UINT ((TypeCode)2) 64.67 +/** A string. */ 64.68 +#define T_STRING ((TypeCode)3) 64.69 +/** An atom. */ 64.70 +#define T_ATOM ((TypeCode)4) 64.71 +/** A boolean. */ 64.72 +#define T_BOOL ((TypeCode)5) 64.73 + 64.74 +/** A cons (pair or list). */ 64.75 +#define T_CONS ((TypeCode)10) 64.76 + 64.77 +/** An error. */ 64.78 +#define T_ERR ((TypeCode)40) 64.79 + 64.80 +/** An atom. */ 64.81 +typedef struct ObjAtom { 64.82 + Sxpr name; 64.83 + Hashcode hashcode; 64.84 + int interned; 64.85 +} ObjAtom; 64.86 + 64.87 +/** A cons (pair). */ 64.88 +typedef struct ObjCons { 64.89 + Sxpr car; 64.90 + Sxpr cdr; 64.91 +} ObjCons; 64.92 + 64.93 +/** A vector. */ 64.94 +typedef struct ObjVector { 64.95 + int n; 64.96 + Sxpr data[0]; 64.97 +} ObjVector; 64.98 + 64.99 +/** Flags for sxpr printing. */ 64.100 +enum PrintFlags { 64.101 + PRINT_RAW = 0x001, 64.102 + PRINT_TYPE = 0x002, 64.103 + PRINT_PRETTY = 0x004, 64.104 + PRINT_NUM = 0x008, 64.105 +}; 64.106 + 64.107 +/** An integer sxpr. 64.108 + * 64.109 + * @param ty type 64.110 + * @param val integer value 64.111 + */ 64.112 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }} 64.113 + 64.114 +/** A pointer sxpr. 64.115 + * If the pointer is non-null, returns an sxpr containing it. 64.116 + * If the pointer is null, returns ONOMEM. 64.117 + * 64.118 + * @param ty type 64.119 + * @param val pointer 64.120 + */ 64.121 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM) 64.122 + 64.123 +/** Make an integer sxpr containing a pointer. 64.124 + * 64.125 + * @param val pointer 64.126 + */ 64.127 +#define PTR(val) OBJP(T_UINT, (void*)(val)) 64.128 + 64.129 +/** Make an integer sxpr. 64.130 + * @param x value 64.131 + */ 64.132 +#define OINT(x) OBJI(T_UINT, x) 64.133 + 64.134 +/** Make an error sxpr. 64.135 + * 64.136 + * @param x value 64.137 + */ 64.138 +#define OERR(x) OBJI(T_ERR, x) 64.139 + 64.140 +/** Out of memory constant. */ 64.141 +#define ONOMEM OBJI(T_NOMEM, 0) 64.142 + 64.143 +/** The `unspecified' constant. */ 64.144 +#define ONONE OBJI(T_NONE, 0) 64.145 + 64.146 +/** Empty list constant. */ 64.147 +#define ONULL OBJI(T_NULL, 0) 64.148 + 64.149 +/** False constant. */ 64.150 +#define OFALSE OBJI(T_BOOL, 0) 64.151 + 64.152 +/** True constant. */ 64.153 +#define OTRUE OBJI(T_BOOL, 1) 64.154 + 64.155 +/* Recognizers for the various sxpr types. */ 64.156 +#define ATOMP(obj) has_type(obj, T_ATOM) 64.157 +#define BOOLP(obj) has_type(obj, T_BOOL) 64.158 +#define CONSP(obj) has_type(obj, T_CONS) 64.159 +#define ERRP(obj) has_type(obj, T_ERR) 64.160 +#define INTP(obj) has_type(obj, T_UINT) 64.161 +#define NOMEMP(obj) has_type(obj, T_NOMEM) 64.162 +#define NONEP(obj) has_type(obj, T_NONE) 64.163 +#define NULLP(obj) has_type(obj, T_NULL) 64.164 +#define STRINGP(obj) has_type(obj, T_STRING) 64.165 + 64.166 +#define TRUEP(obj) get_ul(obj) 64.167 + 64.168 +/** Convert an sxpr to an unsigned integer. */ 64.169 +#define OBJ_UINT(x) get_ul(x) 64.170 +/** Convert an sxpr to an integer. */ 64.171 +#define OBJ_INT(x) (int)get_ul(x) 64.172 + 64.173 +/* Conversions of sxprs to their values. 64.174 + * No checking is done. 64.175 + */ 64.176 +#define OBJ_STRING(x) ((char*)get_ptr(x)) 64.177 +#define OBJ_CONS(x) ((ObjCons*)get_ptr(x)) 64.178 +#define OBJ_ATOM(x) ((ObjAtom*)get_ptr(x)) 64.179 +#define OBJ_SET(x) ((ObjSet*)get_ptr(x)) 64.180 +#define CAR(x) (OBJ_CONS(x)->car) 64.181 +#define CDR(x) (OBJ_CONS(x)->cdr) 64.182 + 64.183 +#define CAAR(x) (CAR(CAR(x))) 64.184 +#define CADR(x) (CAR(CDR(x))) 64.185 +#define CDAR(x) (CDR(CAR(x))) 64.186 +#define CDDR(x) (CDR(CDR(x))) 64.187 + 64.188 +/** Get the integer value from an sxpr. 64.189 + * 64.190 + * @param obj sxpr 64.191 + * @return value 64.192 + */ 64.193 +static inline unsigned long get_ul(Sxpr obj){ 64.194 + return obj.v.ul; 64.195 +} 64.196 + 64.197 +/** Get the pointer value from an sxpr. 64.198 + * 64.199 + * @param obj sxpr 64.200 + * @return value 64.201 + */ 64.202 +static inline void * get_ptr(Sxpr obj){ 64.203 + return obj.v.ptr; 64.204 +} 64.205 + 64.206 +/** Create an sxpr containing a pointer. 64.207 + * 64.208 + * @param type typecode 64.209 + * @param val pointer 64.210 + * @return sxpr 64.211 + */ 64.212 +static inline Sxpr obj_ptr(TypeCode type, void *val){ 64.213 + return (Sxpr){ type: type, v: { ptr: val } }; 64.214 +} 64.215 + 64.216 +/** Create an sxpr containing an integer. 64.217 + * 64.218 + * @param type typecode 64.219 + * @param val integer 64.220 + * @return sxpr 64.221 + */ 64.222 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){ 64.223 + return (Sxpr){ type: type, v: { ul: val } }; 64.224 +} 64.225 + 64.226 +/** Get the type of an sxpr. 64.227 + * 64.228 + * @param obj sxpr 64.229 + * @return type 64.230 + */ 64.231 +static inline TypeCode get_type(Sxpr obj){ 64.232 + return obj.type; 64.233 +} 64.234 + 64.235 +/** Check the type of an sxpr. 64.236 + * 64.237 + * @param obj sxpr 64.238 + * @param type to check 64.239 + * @return 1 if has the type, 0 otherwise 64.240 + */ 64.241 +static inline int has_type(Sxpr obj, TypeCode type){ 64.242 + return get_type(obj) == type; 64.243 +} 64.244 + 64.245 +/** Compare sxprs for literal equality of type and value. 64.246 + * 64.247 + * @param x sxpr to compare 64.248 + * @param y sxpr to compare 64.249 + * @return 1 if equal, 0 otherwise 64.250 + */ 64.251 +static inline int eq(Sxpr x, Sxpr y){ 64.252 + return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y))); 64.253 +} 64.254 + 64.255 +/** Checked version of CAR 64.256 + * 64.257 + * @param x sxpr 64.258 + * @return CAR if a cons, x otherwise 64.259 + */ 64.260 +static inline Sxpr car(Sxpr x){ 64.261 + return (CONSP(x) ? CAR(x) : x); 64.262 +} 64.263 + 64.264 +/** Checked version of CDR. 64.265 + * 64.266 + * @param x sxpr 64.267 + * @return CDR if a cons, null otherwise 64.268 + */ 64.269 +static inline Sxpr cdr(Sxpr x){ 64.270 + return (CONSP(x) ? CDR(x) : ONULL); 64.271 +} 64.272 + 64.273 +/** Allocate some memory and return an sxpr containing it. 64.274 + * Returns ONOMEM if allocation failed. 64.275 + * 64.276 + * @param n number of bytes to allocate 64.277 + * @param ty typecode 64.278 + * @return sxpr 64.279 + */ 64.280 +static inline Sxpr halloc(size_t n, TypeCode ty){ 64.281 + return OBJP(ty, allocate(n)); 64.282 +} 64.283 + 64.284 +/** Allocate an sxpr containing a pointer to the given type. 64.285 + * 64.286 + * @param ty type (uses sizeof to determine how many bytes to allocate) 64.287 + * @param code typecode 64.288 + * @return sxpr, ONOMEM if allocation failed 64.289 + */ 64.290 +#define HALLOC(ty, code) halloc(sizeof(ty), code) 64.291 + 64.292 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags); 64.293 +typedef int ObjEqualFn(Sxpr obj, Sxpr other); 64.294 +typedef void ObjFreeFn(Sxpr obj); 64.295 + 64.296 +/** An sxpr type definition. */ 64.297 +typedef struct SxprType { 64.298 + TypeCode type; 64.299 + char *name; 64.300 + int pointer; 64.301 + ObjPrintFn *print; 64.302 + ObjEqualFn *equal; 64.303 + ObjFreeFn *free; 64.304 +} SxprType; 64.305 + 64.306 + 64.307 +extern SxprType *get_sxpr_type(int ty); 64.308 + 64.309 +/** Free the pointer in an sxpr. 64.310 + * 64.311 + * @param x sxpr containing a pointer 64.312 + */ 64.313 +static inline void hfree(Sxpr x){ 64.314 + deallocate(get_ptr(x)); 64.315 +} 64.316 + 64.317 +extern int objprint(IOStream *io, Sxpr x, unsigned flags); 64.318 +extern int objequal(Sxpr x, Sxpr y); 64.319 +extern void objfree(Sxpr x); 64.320 + 64.321 +extern void cons_free_cells(Sxpr obj); 64.322 +extern Sxpr intern(char *s); 64.323 + 64.324 +extern Sxpr assoc(Sxpr k, Sxpr l); 64.325 +extern Sxpr assocq(Sxpr k, Sxpr l); 64.326 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l); 64.327 +extern Sxpr nrev(Sxpr l); 64.328 +extern Sxpr cons_member(Sxpr l, Sxpr x); 64.329 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 64.330 +extern int cons_subset(Sxpr s, Sxpr t); 64.331 +extern int cons_set_equal(Sxpr s, Sxpr t); 64.332 + 64.333 +#ifdef USE_GC 64.334 +extern Sxpr cons_remove(Sxpr l, Sxpr x); 64.335 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v); 64.336 +#endif 64.337 + 64.338 +extern Sxpr atom_new(char *name); 64.339 +extern char * atom_name(Sxpr obj); 64.340 + 64.341 +extern Sxpr string_new(char *s); 64.342 +extern char * string_string(Sxpr obj); 64.343 +extern int string_length(Sxpr obj); 64.344 + 64.345 +extern Sxpr cons_new(Sxpr car, Sxpr cdr); 64.346 +extern int cons_push(Sxpr *list, Sxpr elt); 64.347 +extern int cons_length(Sxpr obj); 64.348 + 64.349 +Sxpr sxpr_name(Sxpr obj); 64.350 +int sxpr_is(Sxpr obj, char *s); 64.351 +int sxpr_elementp(Sxpr obj, Sxpr name); 64.352 +Sxpr sxpr_attributes(Sxpr obj); 64.353 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def); 64.354 +Sxpr sxpr_children(Sxpr obj); 64.355 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def); 64.356 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def); 64.357 +Sxpr sxpr_child0(Sxpr obj, Sxpr def); 64.358 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def); 64.359 + 64.360 +/** Create a new atom. 64.361 + * 64.362 + * @param s atom name 64.363 + * @return new atom 64.364 + */ 64.365 +static inline Sxpr mkatom(char *s){ 64.366 + return atom_new(s); 64.367 +} 64.368 + 64.369 +/** Create a new string sxpr. 64.370 + * 64.371 + * @param s string bytes (copied) 64.372 + * @return new string 64.373 + */ 64.374 +static inline Sxpr mkstring(char *s){ 64.375 + return string_new(s); 64.376 +} 64.377 + 64.378 +/** Create an integer sxpr. 64.379 + * 64.380 + * @param i value 64.381 + * @return sxpr 64.382 + */ 64.383 +static inline Sxpr mkint(int i){ 64.384 + return OBJI(T_UINT, i); 64.385 +} 64.386 + 64.387 +/** Create a boolean sxpr. 64.388 + * 64.389 + * @param b value 64.390 + * @return sxpr 64.391 + */ 64.392 +static inline Sxpr mkbool(int b){ 64.393 + return OBJI(T_BOOL, (b ? 1 : 0)); 64.394 +} 64.395 + 64.396 +/* Constants used in parsing and printing. */ 64.397 +#define k_list_open "(" 64.398 +#define c_list_open '(' 64.399 +#define k_list_close ")" 64.400 +#define c_list_close ')' 64.401 +#define k_true "true" 64.402 +#define k_false "false" 64.403 + 64.404 +#define c_var '$' 64.405 +#define c_escape '\\' 64.406 +#define c_single_quote '\'' 64.407 +#define c_double_quote '"' 64.408 +#define c_string_open c_double_quote 64.409 +#define c_string_close c_double_quote 64.410 +#define c_data_open '[' 64.411 +#define c_data_close ']' 64.412 +#define c_binary '*' 64.413 +#define c_eval '!' 64.414 +#define c_concat_open '{' 64.415 +#define c_concat_close '}' 64.416 + 64.417 +#endif /* ! _XUTIL_SXPR_H_ */
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 65.2 +++ b/tools/xfrd/xdr.c Tue Jul 06 17:27:27 2004 +0000 65.3 @@ -0,0 +1,316 @@ 65.4 +#include <errno.h> 65.5 +#include "xdr.h" 65.6 + 65.7 +#define MODULE_NAME "XDR" 65.8 +//#define DEBUG 1 65.9 +#undef DEBUG 65.10 +#include "debug.h" 65.11 + 65.12 +/** @file 65.13 + * XDR packer/unpacker for elements. 65.14 + * 65.15 + * string -> [T_STRING] [len:u16] <len bytes> 65.16 + * atom -> [T_ATOM] [len:u16] <len bytes> 65.17 + * uint -> [T_UINT] [value] 65.18 + * cons -> [T_LIST] {1 elt}* 0 65.19 + * null -> [T_NULL] 65.20 + * none -> [T_NONE] 65.21 + * bool -> [T_BOOL] { 0:u8 | 1:u8 } 65.22 + * 65.23 + * types packed as u16. 65.24 + * 65.25 + * So (a b c) -> [T_CONS] a [T_CONS] b [T_CONS] c [T_NULL] 65.26 + * () -> [T_NULL] 65.27 + */ 65.28 + 65.29 +int pack_bool(IOStream *io, int x){ 65.30 + int err=0; 65.31 + //dprintf("> x=%d\n", x); 65.32 + err = IOStream_print(io, "%c", 0xff & x); 65.33 + if(err > 0) err = 0; 65.34 + //dprintf("< err=%d\n", err); 65.35 + return err; 65.36 +} 65.37 + 65.38 +int unpack_bool(IOStream *io, int *x){ 65.39 + int err = 0; 65.40 + int c; 65.41 + //dprintf(">\n"); 65.42 + c = IOStream_getc(io); 65.43 + *x = (c < 0 ? 0 : c); 65.44 + err = IOStream_error(io); 65.45 + if(c < 0 && !err) err = -EIO; 65.46 + //dprintf("< err=%d x=%d\n", err, *x); 65.47 + return err; 65.48 +} 65.49 + 65.50 +int pack_ushort(IOStream *io, unsigned short x){ 65.51 + int err=0; 65.52 + //dprintf("> x=%u\n", x); 65.53 + err = IOStream_print(io, "%c%c", 65.54 + 0xff & (x >> 8), 65.55 + 0xff & (x )); 65.56 + if(err > 0) err = 0; 65.57 + //dprintf("< err=%d\n", err); 65.58 + return err; 65.59 +} 65.60 + 65.61 +int unpack_ushort(IOStream *io, unsigned short *x){ 65.62 + int err = 0; 65.63 + int i, c = 0; 65.64 + //dprintf(">\n"); 65.65 + *x = 0; 65.66 + for(i = 0; i< 2; i++){ 65.67 + c = IOStream_getc(io); 65.68 + if(c < 0) break; 65.69 + *x <<= 8; 65.70 + *x |= (0xff & c); 65.71 + } 65.72 + err = IOStream_error(io); 65.73 + 65.74 + if(c < 0 && !err) err = -EIO; 65.75 + //dprintf("< err=%d x=%u\n", err, *x); 65.76 + return err; 65.77 +} 65.78 + 65.79 +int pack_type(IOStream *io, unsigned short x){ 65.80 + return pack_ushort(io, x); 65.81 +} 65.82 + 65.83 +int unpack_type(IOStream *io, unsigned short *x){ 65.84 + return unpack_ushort(io, x); 65.85 +} 65.86 + 65.87 +int pack_uint(IOStream *io, unsigned int x){ 65.88 + int err=0; 65.89 + //dprintf("> x=%u\n", x); 65.90 + err = IOStream_print(io, "%c%c%c%c", 65.91 + 0xff & (x >> 24), 65.92 + 0xff & (x >> 16), 65.93 + 0xff & (x >> 8), 65.94 + 0xff & (x )); 65.95 + if(err > 0) err = 0; 65.96 + //dprintf("< err=%d\n", err); 65.97 + return err; 65.98 +} 65.99 + 65.100 +int unpack_uint(IOStream *io, unsigned int *x){ 65.101 + int err = 0; 65.102 + int i, c = 0; 65.103 + //dprintf(">\n"); 65.104 + *x = 0; 65.105 + for(i = 0; i< 4; i++){ 65.106 + c = IOStream_getc(io); 65.107 + if(c < 0) break; 65.108 + *x <<= 8; 65.109 + *x |= (0xff & c); 65.110 + } 65.111 + err = IOStream_error(io); 65.112 + if(c < 0 && !err) err = -EIO; 65.113 + //dprintf("< err=%d x=%u\n", err, *x); 65.114 + return err; 65.115 +} 65.116 + 65.117 +int pack_string(IOStream *io, Sxpr x){ 65.118 + int err = 0; 65.119 + unsigned short n = 0xffff & string_length(x); 65.120 + char *s = string_string(x); 65.121 + int i; 65.122 + //dprintf("> n=%d s=%s\n", n, s); 65.123 + err = pack_ushort(io, n); 65.124 + if(err) goto exit; 65.125 + for(i = 0; i < n; i++){ 65.126 + err = IOStream_print(io, "%c", s[i]); 65.127 + if(err < 0) break; 65.128 + } 65.129 + if(err > 0) err = 0; 65.130 + exit: 65.131 + //dprintf("< err=%d\n", err); 65.132 + return err; 65.133 +} 65.134 + 65.135 +int unpack_string(IOStream *io, Sxpr *x){ 65.136 + int err; 65.137 + unsigned short n; 65.138 + int i, c = 0; 65.139 + char *s; 65.140 + Sxpr val = ONONE; 65.141 + 65.142 + //dprintf(">\n"); 65.143 + err = unpack_ushort(io, &n); 65.144 + if(err) goto exit; 65.145 + val = halloc(n+1, T_STRING); 65.146 + if(NOMEMP(val)){ 65.147 + err = -ENOMEM; 65.148 + goto exit; 65.149 + } 65.150 + s = string_string(val); 65.151 + for(i=0; i<n; i++){ 65.152 + c = IOStream_getc(io); 65.153 + if(c < 0) break; 65.154 + s[i] = (char)c; 65.155 + } 65.156 + s[n] = '\0'; 65.157 + exit: 65.158 + err = IOStream_error(io); 65.159 + if(c < 0 && !err) err = -EIO; 65.160 + if(err){ 65.161 + objfree(val); 65.162 + val = ONONE; 65.163 + } 65.164 + *x = val; 65.165 + //IOStream_print(iostdout, "n=%d str=", n); 65.166 + //objprint(iostdout, *x, 0); 65.167 + //IOStream_print(iostdout, "\n"); 65.168 + //dprintf("< err=%d\n", err); 65.169 + return err; 65.170 +} 65.171 + 65.172 +int pack_cons(IOStream *io, Sxpr x){ 65.173 + int err = 0; 65.174 + Sxpr l; 65.175 + //dprintf(">\n"); 65.176 + for(l = x; CONSP(l); l = CDR(l)){ 65.177 + err = pack_bool(io, 1); 65.178 + if(err) goto exit; 65.179 + err = pack_sxpr(io, CAR(l)); 65.180 + if(err) goto exit; 65.181 + } 65.182 + err = pack_bool(io, 0); 65.183 + exit: 65.184 + //dprintf("< err=%d\n", err); 65.185 + return err; 65.186 +} 65.187 + 65.188 +int unpack_cons(IOStream *io, Sxpr *x){ 65.189 + int err = 0; 65.190 + int more = 0; 65.191 + Sxpr u = ONONE, v = ONONE, val = ONULL; 65.192 + 65.193 + dprintf(">\n"); 65.194 + while(1){ 65.195 + err = unpack_bool(io, &more); 65.196 + if(err) goto exit; 65.197 + if(!more){ 65.198 + //IOStream_print(iostdout, "unpack_cons 1 val="); 65.199 + ////objprint(iostdout, val, 0); 65.200 + IOStream_print(iostdout, "\n"); 65.201 + 65.202 + val = nrev(val); 65.203 + 65.204 + //IOStream_print(iostdout, "unpack_cons 2 val="); 65.205 + //objprint(iostdout, val, 0); 65.206 + //IOStream_print(iostdout, "\n"); 65.207 + 65.208 + break; 65.209 + } 65.210 + err = unpack_sxpr(io, &u); 65.211 + if(err) goto exit; 65.212 + v = cons_new(u, val); 65.213 + if(NOMEMP(v)){ 65.214 + err = -ENOMEM; 65.215 + objfree(u); 65.216 + goto exit; 65.217 + } 65.218 + val = v; 65.219 + } 65.220 + exit: 65.221 + if(err){ 65.222 + objfree(val); 65.223 + val = ONONE; 65.224 + } 65.225 + *x = val; 65.226 + dprintf("< err=%d\n", err); 65.227 + return err; 65.228 +} 65.229 + 65.230 +int pack_sxpr(IOStream *io, Sxpr x){ 65.231 + int err = 0; 65.232 + unsigned short type = get_type(x); 65.233 + //dprintf(">\n"); 65.234 + //objprint(iostdout, x, 0); 65.235 + //IOStream_print(iostdout, "\n"); 65.236 + 65.237 + err = pack_type(io, type); 65.238 + if(err) goto exit; 65.239 + switch(type){ 65.240 + case T_NULL: 65.241 + break; 65.242 + case T_NONE: 65.243 + break; 65.244 + case T_BOOL: 65.245 + err = pack_bool(io, get_ul(x)); 65.246 + break; 65.247 + case T_CONS: 65.248 + err = pack_cons(io, x); 65.249 + break; 65.250 + case T_ATOM: 65.251 + err = pack_string(io, OBJ_ATOM(x)->name); 65.252 + break; 65.253 + case T_STRING: 65.254 + err = pack_string(io, x); 65.255 + break; 65.256 + case T_UINT: 65.257 + err = pack_uint(io, get_ul(x)); 65.258 + break; 65.259 + default: 65.260 + err = -EINVAL; 65.261 + IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type); 65.262 + break; 65.263 + } 65.264 + exit: 65.265 + //dprintf("< err=%d\n", err); 65.266 + return err; 65.267 +} 65.268 + 65.269 +int unpack_sxpr(IOStream *io, Sxpr *x){ 65.270 + int err = 0; 65.271 + unsigned short type; 65.272 + unsigned int u; 65.273 + Sxpr val = ONONE, y; 65.274 + 65.275 + //dprintf(">\n"); 65.276 + err = unpack_type(io, &type); 65.277 + if(err) goto exit; 65.278 + switch(type){ 65.279 + case T_NULL: 65.280 + val = ONULL; 65.281 + break; 65.282 + case T_NONE: 65.283 + val = ONONE; 65.284 + break; 65.285 + case T_CONS: 65.286 + err = unpack_cons(io, &val); 65.287 + break; 65.288 + case T_BOOL: 65.289 + err = unpack_bool(io, &u); 65.290 + if(err) goto exit; 65.291 + val = (u ? OTRUE : OFALSE); 65.292 + break; 65.293 + case T_ATOM: 65.294 + err = unpack_string(io, &y); 65.295 + if(err) goto exit; 65.296 + val = intern(string_string(y)); 65.297 + objfree(y); 65.298 + break; 65.299 + case T_STRING: 65.300 + err = unpack_string(io, &val); 65.301 + break; 65.302 + case T_UINT: 65.303 + err = unpack_uint(io, &u); 65.304 + if(err) goto exit; 65.305 + val = OBJI(type, u); 65.306 + break; 65.307 + default: 65.308 + err = -EINVAL; 65.309 + IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type); 65.310 + break; 65.311 + } 65.312 + exit: 65.313 + *x = (err ? ONONE : val); 65.314 + //IOStream_print(iostdout, "sxpr="); 65.315 + //objprint(iostdout, *x, 0); 65.316 + //IOStream_print(iostdout, "\n"); 65.317 + //dprintf("< err=%d\n", err); 65.318 + return err; 65.319 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/tools/xfrd/xdr.h Tue Jul 06 17:27:27 2004 +0000 66.3 @@ -0,0 +1,30 @@ 66.4 +#ifndef _XUTIL_XDR_H_ 66.5 +#define _XUTIL_XDR_H_ 66.6 +#include "iostream.h" 66.7 +#include "sxpr.h" 66.8 + 66.9 +int pack_type(IOStream *io, unsigned short x); 66.10 + 66.11 +int unpack_type(IOStream *io, unsigned short *x); 66.12 + 66.13 +int pack_bool(IOStream *io, int x); 66.14 + 66.15 +int unpack_bool(IOStream *io, int *x); 66.16 + 66.17 +int pack_uint(IOStream *out, unsigned int x); 66.18 + 66.19 +int unpack_uint(IOStream *in, unsigned int *x); 66.20 + 66.21 +int pack_string(IOStream *out, Sxpr x); 66.22 + 66.23 +int unpack_string(IOStream *in, Sxpr *x); 66.24 + 66.25 +int pack_cons(IOStream *out, Sxpr x); 66.26 + 66.27 +int unpack_cons(IOStream *in, Sxpr *x); 66.28 + 66.29 +int pack_sxpr(IOStream *out, Sxpr x); 66.30 + 66.31 +int unpack_sxpr(IOStream *in, Sxpr *x); 66.32 + 66.33 +#endif /* _XUTIL_XDR_H_ */
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/tools/xfrd/xen_domain.c Tue Jul 06 17:27:27 2004 +0000 67.3 @@ -0,0 +1,90 @@ 67.4 +#include <unistd.h> 67.5 +#include <stdlib.h> 67.6 +#include <stdio.h> 67.7 + 67.8 +#ifndef _XEN_XFR_STUB_ 67.9 +#include "dom0_defs.h" 67.10 +#include "mem_defs.h" 67.11 +#endif 67.12 + 67.13 +#include "xen_domain.h" 67.14 +#include "marshal.h" 67.15 +#include "xdr.h" 67.16 + 67.17 +#define MODULE_NAME "XFRD" 67.18 +#define DEBUG 1 67.19 +#include "debug.h" 67.20 + 67.21 +/** Write domain state. 67.22 + * 67.23 + * At some point during this the domain is suspended, and then there's no way back. 67.24 + * Even if something later goes wrong we can't restart the domain. 67.25 + */ 67.26 +int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n){ 67.27 + int err = 0; 67.28 + char buf[1024]; 67.29 + int n, k, d, buf_n; 67.30 + dprintf("> dom=%d\n", dom); 67.31 +#ifdef _XEN_XFR_STUB_ 67.32 + err = marshal_uint32(io, dom); 67.33 + if(err) goto exit; 67.34 + err = marshal_string(io, vmconfig, vmconfig_n); 67.35 + if(err) goto exit; 67.36 + n = 32 * 1024 * 1024; 67.37 + buf_n = sizeof(buf); 67.38 + err = marshal_uint32(io, n); 67.39 + for(k = 0; k < n; k += d){ 67.40 + d = n - k; 67.41 + if(d > buf_n) d = buf_n; 67.42 + err = marshal_bytes(io, buf, d); 67.43 + if(err) goto exit; 67.44 + //dprintf("> k=%d n=%d\n", k, n); 67.45 + } 67.46 + 67.47 + exit: 67.48 +#else 67.49 +#endif 67.50 + dprintf("< err=%d\n", err); 67.51 + return err; 67.52 +} 67.53 + 67.54 +/** Receive domain state. 67.55 + * Create a new domain and store the received state into it. 67.56 + */ 67.57 +int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n){ 67.58 + int err = 0; 67.59 + char buf[1024]; 67.60 + int n, k, d, buf_n; 67.61 + dprintf(">\n"); 67.62 +#ifdef _XEN_XFR_STUB_ 67.63 + err = unmarshal_uint32(io, dom); 67.64 + if(err) goto exit; 67.65 + err = unmarshal_new_string(io, vmconfig, vmconfig_n); 67.66 + if(err) goto exit; 67.67 + err = unmarshal_uint32(io, &n); 67.68 + buf_n = sizeof(buf); 67.69 + for(k = 0; k < n; k += d){ 67.70 + d = n - k; 67.71 + if(d > buf_n) d = buf_n; 67.72 + err = unmarshal_bytes(io, buf, d); 67.73 + if(err) goto exit; 67.74 + //dprintf("> k=%d n=%d\n", k, n); 67.75 + } 67.76 + exit: 67.77 +#else 67.78 +#endif 67.79 + dprintf("< err=%d\n", err); 67.80 + return err; 67.81 +} 67.82 + 67.83 +/** Configure a new domain. Talk to xend. Use libcurl? 67.84 + */ 67.85 +int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){ 67.86 + int err = 0; 67.87 + dprintf(">\n"); 67.88 +#ifdef _XEN_XFR_STUB_ 67.89 +#else 67.90 +#endif 67.91 + dprintf("< err=%d\n", err); 67.92 + return err; 67.93 +}
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/tools/xfrd/xen_domain.h Tue Jul 06 17:27:27 2004 +0000 68.3 @@ -0,0 +1,15 @@ 68.4 +#ifndef _XFRD_XEN_DOMAIN_H_ 68.5 +#define _XFRD_XEN_DOMAIN_H_ 68.6 +#include <sys/types.h> 68.7 +#include <iostream.h> 68.8 +#include "connection.h" 68.9 + 68.10 +/** Define to use stubs. Undefine to use Xen ops. */ 68.11 +//#define _XEN_XFR_STUB_ 68.12 + 68.13 +extern int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int vmconfig_n); 68.14 +extern int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n); 68.15 + 68.16 + 68.17 +extern int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n); 68.18 +#endif
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 69.2 +++ b/tools/xfrd/xfrd.c Tue Jul 06 17:27:27 2004 +0000 69.3 @@ -0,0 +1,1127 @@ 69.4 +/** @file 69.5 + * XFRD - Domain Transfer Daemon for Xen. 69.6 + * 69.7 + * The xfrd is forked by xend to transfer a vm to a remote system. 69.8 + * 69.9 + * The vm is suspended, then its state and memory are transferred to the remote system. 69.10 + * The remote system attempts to create a vm and copy the transferred state and memory into it, 69.11 + * finally resuming the vm. If all is OK the vm ends up running on the remote 69.12 + * system and is removed from the originating system. If the transfer does not complete 69.13 + * successfully the originating system attempts to resume the vm. 69.14 + * The children exit when the transfer completes. 69.15 + * 69.16 + * @author Mike Wray <mike.wray@hpl.hp.com> 69.17 + */ 69.18 + 69.19 +#include <stdlib.h> 69.20 +#include <unistd.h> 69.21 +#include <stdio.h> 69.22 +#include <getopt.h> 69.23 +#include <errno.h> 69.24 +#include <sys/types.h> 69.25 +#include <time.h> 69.26 +#include <sys/socket.h> 69.27 +#include <netinet/in.h> 69.28 +#include <arpa/inet.h> 69.29 +#include <string.h> 69.30 + 69.31 +#include <signal.h> 69.32 +#include <sys/wait.h> 69.33 +#include <sys/select.h> 69.34 + 69.35 +#include "allocate.h" 69.36 +#include "file_stream.h" 69.37 +#include "string_stream.h" 69.38 +#include "lzi_stream.h" 69.39 +#include "sys_net.h" 69.40 +#include "sys_string.h" 69.41 + 69.42 +#include "xdr.h" 69.43 +#include "enum.h" 69.44 +#include "xfrd.h" 69.45 + 69.46 +#include "xen_domain.h" 69.47 + 69.48 +#include "connection.h" 69.49 +#include "select.h" 69.50 + 69.51 +#define MODULE_NAME "XFRD" 69.52 +#define DEBUG 1 69.53 +#include "debug.h" 69.54 + 69.55 +/* 69.56 +sender: 69.57 + xend connects to xfrd and writes migrate message 69.58 + xend writes domain config to xfrd 69.59 + 69.60 + xfrd forks 69.61 + 69.62 + xfrd connects to peer 69.63 + xfrd sends hello, reads response 69.64 + xfrd sends domain 69.65 + xfrd reads response 69.66 + reports progress/status to xend 69.67 + 69.68 + xend reads xfrd for progress/status, disconnects 69.69 + If ok, destroys domain. 69.70 + If not ok, unpauses domain. 69.71 + 69.72 +receiver: 69.73 + xfrd accepts connection on inbound port 69.74 + xfrd forks and accepts connection 69.75 + xfrd receives hello, writes response 69.76 + xfrd receives domain 69.77 + xfrd connects to xend, configures new domain 69.78 + xfrd writes status back to peer, child exits 69.79 + 69.80 + 69.81 + (xfr.hello <major> <minor>) 69.82 + (xfr.err <code> <reason>) 69.83 + 69.84 + xend->xfrd (xfr.migrate <domain> <vmconfig> <host> <port>) 69.85 + (xfr.save <domain> <vmconfig> <file>) 69.86 + xfrd->xend (xfr.suspend <domain>) 69.87 + xfrd->xend (xfr.progress <percent> <rate: kb/s>) 69.88 + xfrd->xend (xfr.err <code> <reason>) | (xfr.ok <domain>) 69.89 + xfrd->xfrd (xfr.xfr <domain>) 69.90 + xfrd->xfrd (xfr.err <code>) | (xfr.ok <domain>) 69.91 + 69.92 + xfrd->xend (xfr.configure <domain> <vmconfig>) 69.93 + */ 69.94 + 69.95 +Sxpr oxfr_configure; // (xfr.configure <vmid> <vmconfig>) 69.96 +Sxpr oxfr_err; // (xfr.err <code>) 69.97 +Sxpr oxfr_hello; // (xfr.hello <major> <minor>) 69.98 +Sxpr oxfr_migrate; // (xfr.migrate <vmid> <vmconfig> <host> <port>) 69.99 +Sxpr oxfr_ok; // (xfr.ok <value>) 69.100 +Sxpr oxfr_progress; // (xfr.progress <percent> <rate: kb/s>) 69.101 +Sxpr oxfr_save; // (xfr.save <vmid> <vmconfig> <file>) 69.102 +Sxpr oxfr_suspend; // (xfr.suspend <vmid>) 69.103 +Sxpr oxfr_xfr; // (xfr.xfr <vmid>) 69.104 + 69.105 +void xfr_init(void){ 69.106 + oxfr_configure = intern("xfr.configure"); 69.107 + oxfr_err = intern("xfr.err"); 69.108 + oxfr_hello = intern("xfr.hello"); 69.109 + oxfr_migrate = intern("xfr.migrate"); 69.110 + oxfr_ok = intern("xfr.ok"); 69.111 + oxfr_progress = intern("xfr.progress"); 69.112 + oxfr_save = intern("xfr.save"); 69.113 + oxfr_suspend = intern("xfr.suspend"); 69.114 + oxfr_xfr = intern("xfr.xfr"); 69.115 +} 69.116 + 69.117 +#ifndef TRUE 69.118 +#define TRUE 1 69.119 +#endif 69.120 + 69.121 +#ifndef FALSE 69.122 +#define FALSE 0 69.123 +#endif 69.124 + 69.125 +#define PROGRAM "xfrd" 69.126 + 69.127 +#define OPT_PORT 'P' 69.128 +#define KEY_PORT "port" 69.129 +#define DOC_PORT "<port>\n\txfr port (as a number or service name)" 69.130 + 69.131 +#define OPT_COMPRESS 'Z' 69.132 +#define KEY_COMPRESS "compress" 69.133 +#define DOC_COMPRESS "\n\tuse compression for migration" 69.134 + 69.135 +#define OPT_HELP 'h' 69.136 +#define KEY_HELP "help" 69.137 +#define DOC_HELP "\n\tprint help" 69.138 + 69.139 +#define OPT_VERSION 'v' 69.140 +#define KEY_VERSION "version" 69.141 +#define DOC_VERSION "\n\tprint version" 69.142 + 69.143 +#define OPT_VERBOSE 'V' 69.144 +#define KEY_VERBOSE "verbose" 69.145 +#define DOC_VERBOSE "\n\tverbose flag" 69.146 + 69.147 +/** Print a usage message. 69.148 + * Prints to stdout if err is zero, and exits with 0. 69.149 + * Prints to stderr if err is non-zero, and exits with 1. 69.150 + */ 69.151 +void usage(int err){ 69.152 + FILE *out = (err ? stderr : stdout); 69.153 + 69.154 + fprintf(out, "Usage: %s [options]\n", PROGRAM); 69.155 + fprintf(out, "-%c, --%s %s\n", OPT_PORT, KEY_PORT, DOC_PORT); 69.156 + fprintf(out, "-%c, --%s %s\n", OPT_COMPRESS, KEY_COMPRESS, DOC_COMPRESS); 69.157 + fprintf(out, "-%c, --%s %s\n", OPT_VERBOSE, KEY_VERBOSE, DOC_VERBOSE); 69.158 + fprintf(out, "-%c, --%s %s\n", OPT_VERSION, KEY_VERSION, DOC_VERSION); 69.159 + fprintf(out, "-%c, --%s %s\n", OPT_HELP, KEY_HELP, DOC_HELP); 69.160 + exit(err ? 1 : 0); 69.161 +} 69.162 + 69.163 +/** Short options. Options followed by ':' take an argument. */ 69.164 +static char *short_opts = (char[]){ 69.165 + OPT_PORT, ':', 69.166 + OPT_COMPRESS, 69.167 + OPT_HELP, 69.168 + OPT_VERSION, 69.169 + OPT_VERBOSE, 69.170 + 0 }; 69.171 + 69.172 +/** Long options. */ 69.173 +static struct option const long_opts[] = { 69.174 + { KEY_PORT, required_argument, NULL, OPT_PORT }, 69.175 + { KEY_COMPRESS, no_argument, NULL, OPT_COMPRESS }, 69.176 + { KEY_HELP, no_argument, NULL, OPT_HELP }, 69.177 + { KEY_VERSION, no_argument, NULL, OPT_VERSION }, 69.178 + { KEY_VERBOSE, no_argument, NULL, OPT_VERBOSE }, 69.179 + { NULL, 0, NULL, 0 } 69.180 +}; 69.181 + 69.182 +typedef struct Args { 69.183 + int bufsize; 69.184 + unsigned long port; 69.185 + int verbose; 69.186 + int compress; 69.187 +} Args; 69.188 + 69.189 +/** Transfer states. */ 69.190 +enum { 69.191 + XFR_INIT, 69.192 + XFR_HELLO, 69.193 + XFR_STATE, 69.194 + XFR_RUN, 69.195 + XFR_FAIL, 69.196 + XFR_DONE, 69.197 + XFR_MAX 69.198 +}; 69.199 + 69.200 +/** Initialize an array element for a constant to its string name. */ 69.201 +#define VALDEF(val) { val, #val } 69.202 + 69.203 +/** Names for the transfer states. */ 69.204 +static EnumDef xfr_states[] = { 69.205 + VALDEF(XFR_INIT), 69.206 + VALDEF(XFR_HELLO), 69.207 + VALDEF(XFR_STATE), 69.208 + VALDEF(XFR_RUN), 69.209 + VALDEF(XFR_FAIL), 69.210 + VALDEF(XFR_DONE), 69.211 + { 0, NULL } 69.212 +}; 69.213 + 69.214 + 69.215 +/** State machine for transfer. */ 69.216 +typedef struct XfrState { 69.217 + /** Current state. */ 69.218 + int state; 69.219 + /** Error codes for the states. */ 69.220 + int state_err[XFR_MAX]; 69.221 + /** First error. */ 69.222 + int err; 69.223 + /** State when first error happened. */ 69.224 + int err_state; 69.225 + 69.226 + uint32_t vmid; 69.227 + char* vmconfig; 69.228 + int vmconfig_n; 69.229 + unsigned long xfr_port; 69.230 + char *xfr_host; 69.231 + uint32_t vmid_new; 69.232 +} XfrState; 69.233 + 69.234 +/** Get the name of a transfer state. 69.235 + * 69.236 + * @param s state 69.237 + * @return name 69.238 + */ 69.239 +char * xfr_state_name(int s){ 69.240 + return enum_val_to_name(s, xfr_states); 69.241 +} 69.242 + 69.243 +/** Set the state of a transfer. 69.244 + * 69.245 + * @param s transfer 69.246 + * @param state state 69.247 + * @return state 69.248 + */ 69.249 +int XfrState_set_state(XfrState *s, int state){ 69.250 + s->state = state; 69.251 + return s->state; 69.252 +} 69.253 + 69.254 +/** Get the state of a transfer. 69.255 + * 69.256 + * @param s transfer 69.257 + * @return state 69.258 + */ 69.259 +int XfrState_get_state(XfrState *s){ 69.260 + return s->state; 69.261 +} 69.262 + 69.263 +/** Set an error in the current state. 69.264 + * Does nothing if an error is already set. 69.265 + * 69.266 + * @param s transfer 69.267 + * @param err error 69.268 + * @return error 69.269 + */ 69.270 +int XfrState_set_err(XfrState *s, int err){ 69.271 + if(!s->state_err[s->state]){ 69.272 + s->state_err[s->state] = err; 69.273 + } 69.274 + if(!s->err){ 69.275 + s->err = err; 69.276 + s->err_state = s->state; 69.277 + } 69.278 + return err; 69.279 +} 69.280 + 69.281 +/** Get the error in the current state. 69.282 + * 69.283 + * @param s transfer 69.284 + * @return error 69.285 + */ 69.286 +int XfrState_get_err(XfrState *s){ 69.287 + return s->state_err[s->state]; 69.288 +} 69.289 + 69.290 +/** Get the first error of a transfer. 69.291 + * 69.292 + * @param s transfer 69.293 + * @return error 69.294 + */ 69.295 +int XfrState_first_err(XfrState *s){ 69.296 + return s->err; 69.297 +} 69.298 + 69.299 +/** Get the state a transfer was in when it had its first error. 69.300 + * 69.301 + * @param s transfer 69.302 + * @return error state 69.303 + */ 69.304 +int XfrState_first_err_state(XfrState *s){ 69.305 + return s->err_state; 69.306 +} 69.307 + 69.308 +/** Xfrd arguments. */ 69.309 +static Args _args = {}; 69.310 + 69.311 +/** Xfrd arguments. */ 69.312 +static Args *args = &_args; 69.313 + 69.314 +/** Set xfrd default arguments. 69.315 + * 69.316 + * @param args arguments to set 69.317 + */ 69.318 +void set_defaults(Args *args){ 69.319 + args->compress = FALSE; 69.320 + args->bufsize = 128 * 1024; 69.321 + args->port = htons(XFRD_PORT); 69.322 +} 69.323 + 69.324 +int stringof(Sxpr exp, char **s){ 69.325 + int err = 0; 69.326 + dprintf(">\n"); 69.327 + objprint(iostdout, exp, PRINT_TYPE); IOStream_print(iostdout, "\n"); 69.328 + if(ATOMP(exp)){ 69.329 + *s = atom_name(exp); 69.330 + } else if(STRINGP(exp)){ 69.331 + *s = string_string(exp); 69.332 + } else { 69.333 + err = -EINVAL; 69.334 + *s = NULL; 69.335 + } 69.336 + dprintf("< err=%d s=%s\n", err, *s); 69.337 + return err; 69.338 +} 69.339 + 69.340 +int intof(Sxpr exp, int *v){ 69.341 + int err = 0; 69.342 + char *s; 69.343 + unsigned long l; 69.344 + dprintf(">\n"); 69.345 + objprint(iostdout, exp, 0); IOStream_print(iostdout, "\n"); 69.346 + if(INTP(exp)){ 69.347 + *v = OBJ_INT(exp); 69.348 + } else { 69.349 + err = stringof(exp, &s); 69.350 + if(err) goto exit; 69.351 + err = convert_atoul(s, &l); 69.352 + *v = (int)l; 69.353 + } 69.354 + exit: 69.355 + dprintf("< err=%d v=%d\n", err, *v); 69.356 + return err; 69.357 +} 69.358 + 69.359 +int addrof(Sxpr exp, uint32_t *v){ 69.360 + char *h; 69.361 + unsigned long a; 69.362 + int err = 0; 69.363 + dprintf(">\n"); 69.364 + objprint(iostdout, exp, 0); IOStream_print(iostdout, "\n"); 69.365 + err = stringof(exp, &h); 69.366 + if(err) goto exit; 69.367 + if(get_host_address(h, &a)){ 69.368 + *v = a; 69.369 + } else { 69.370 + err = -EINVAL; 69.371 + } 69.372 + exit: 69.373 + dprintf("< err=%d v=%x\n", err, *v); 69.374 + return err; 69.375 +} 69.376 + 69.377 +int portof(Sxpr exp, uint16_t *v){ 69.378 + char *s; 69.379 + int err = 0; 69.380 + dprintf(">\n"); 69.381 + objprint(iostdout, exp, 0); IOStream_print(iostdout, "\n"); 69.382 + if(INTP(exp)){ 69.383 + *v = get_ul(exp); 69.384 + *v = htons(*v); 69.385 + } else { 69.386 + unsigned long p; 69.387 + err = stringof(exp, &s); 69.388 + if(err) goto exit; 69.389 + if(get_service_port(s, &p)){ 69.390 + *v = p; 69.391 + } else { 69.392 + err = -EINVAL; 69.393 + } 69.394 + } 69.395 + exit: 69.396 + dprintf("< err=%d v=%u\n", err, *v); 69.397 + return err; 69.398 +} 69.399 + 69.400 +static inline struct in_addr inaddr(uint32_t addr){ 69.401 + return (struct in_addr){ .s_addr = addr }; 69.402 +} 69.403 + 69.404 +time_t stats(time_t t0, uint64_t offset, uint64_t memory, float *percent, float *rate){ 69.405 + time_t t1 = time(NULL); 69.406 + *percent = (offset * 100.0f) / memory; 69.407 + t1 = time(NULL) - t0; 69.408 + *rate = (t1 ? offset/(t1 * 1024.0f) : 0.0f); 69.409 + return t1; 69.410 +} 69.411 + 69.412 +/** Notify success or error. 69.413 + * 69.414 + * @param conn connection 69.415 + * @param errcode error code 69.416 + * @return 0 on success, error code otherwise 69.417 + */ 69.418 +int xfr_error(Conn *conn, int errcode){ 69.419 + int err = 0; 69.420 + if(!conn->out) return -ENOTCONN; 69.421 + err = pack_type(conn->out, T_CONS); 69.422 + if(err) goto exit; 69.423 + err = pack_bool(conn->out, 1); 69.424 + if(err) goto exit; 69.425 + err = pack_sxpr(conn->out, oxfr_err); 69.426 + if(err) goto exit; 69.427 + err = pack_bool(conn->out, 1); 69.428 + if(err) goto exit; 69.429 + err = pack_sxpr(conn->out, mkint(errcode)); 69.430 + if(err) goto exit; 69.431 + err = pack_bool(conn->out, 0); 69.432 + exit: 69.433 + return err; 69.434 +} 69.435 + 69.436 +/** Read a response message - error or ok. 69.437 + * 69.438 + * @param conn connection 69.439 + * @return 0 on success, error code otherwise 69.440 + */ 69.441 +int xfr_response(Conn *conn){ 69.442 + int err; 69.443 + Sxpr sxpr; 69.444 + 69.445 + dprintf(">\n"); 69.446 + if(!conn->out) return -ENOTCONN; 69.447 + err = unpack_sxpr(conn->in, &sxpr); 69.448 + if(err) goto exit; 69.449 + if(sxpr_elementp(sxpr, oxfr_err)){ 69.450 + int errcode; 69.451 + err = intof(sxpr_childN(sxpr, 0, ONONE), &errcode); 69.452 + if(err) goto exit; 69.453 + err = errcode; 69.454 + } 69.455 + exit: 69.456 + dprintf("< err=%d\n", err); 69.457 + return err; 69.458 +} 69.459 + 69.460 +/** Get the initial hello message and check the protocol version. 69.461 + * It is an error to receive anything other than a hello message 69.462 + * with the correct protocol version. 69.463 + * 69.464 + * @param conn connection 69.465 + * @return 0 on success, error code otherwise 69.466 + */ 69.467 +int xfr_hello(Conn *conn){ 69.468 + int err; 69.469 + uint32_t major = XFR_PROTO_MAJOR, minor = XFR_PROTO_MINOR; 69.470 + uint32_t hello_major, hello_minor; 69.471 + Sxpr sxpr; 69.472 + if(!conn->in) return -ENOTCONN; 69.473 + dprintf(">\n"); 69.474 + err = unpack_sxpr(conn->in, &sxpr); 69.475 + if(err) goto exit; 69.476 + if(!sxpr_elementp(sxpr, oxfr_hello)){ 69.477 + dprintf("> sxpr_elementp test failed\n"); 69.478 + err = -EINVAL; 69.479 + goto exit; 69.480 + } 69.481 + err = intof(sxpr_childN(sxpr, 0, ONONE), &hello_major); 69.482 + if(err) goto exit; 69.483 + err = intof(sxpr_childN(sxpr, 1, ONONE), &hello_minor); 69.484 + if(err) goto exit; 69.485 + if(hello_major != major || hello_minor != minor){ 69.486 + eprintf("> Wanted protocol version %d.%d, got %d.%d", 69.487 + major, minor, hello_major, hello_minor); 69.488 + err = -EINVAL; 69.489 + goto exit; 69.490 + } 69.491 + exit: 69.492 + xfr_error(conn, err); 69.493 + if(err){ 69.494 + eprintf("> Hello failed: %d\n", err); 69.495 + } 69.496 + dprintf("< err=%d\n", err); 69.497 + return err; 69.498 +} 69.499 + 69.500 +/** Send the initial hello message. 69.501 + * 69.502 + * @param conn connection 69.503 + * @param msg message 69.504 + * @return 0 on success, error code otherwise 69.505 + */ 69.506 +int xfr_send_hello(Conn *conn){ 69.507 + int err = 0; 69.508 + dprintf(">\n"); 69.509 + err = pack_type(conn->out, T_CONS); 69.510 + if(err) goto exit; 69.511 + err = pack_bool(conn->out, 1); 69.512 + if(err) goto exit; 69.513 + err = pack_sxpr(conn->out, oxfr_hello); 69.514 + if(err) goto exit; 69.515 + err = pack_bool(conn->out, 1); 69.516 + if(err) goto exit; 69.517 + err = pack_sxpr(conn->out, mkint(XFR_PROTO_MAJOR)); 69.518 + if(err) goto exit; 69.519 + err = pack_bool(conn->out, 1); 69.520 + if(err) goto exit; 69.521 + err = pack_sxpr(conn->out, mkint(XFR_PROTO_MINOR)); 69.522 + if(err) goto exit; 69.523 + err = pack_bool(conn->out, 0); 69.524 + IOStream_flush(conn->out); 69.525 + dprintf("> xfr_response...\n"); 69.526 + err = xfr_response(conn); 69.527 + exit: 69.528 + dprintf("< err=%d\n", err); 69.529 + return err; 69.530 +} 69.531 + 69.532 +int xfr_send_xfr(Conn *conn, uint32_t vmid){ 69.533 + int err; 69.534 + err = pack_type(conn->out, T_CONS); 69.535 + if(err) goto exit; 69.536 + err = pack_bool(conn->out, 1); 69.537 + if(err) goto exit; 69.538 + err = pack_sxpr(conn->out, oxfr_xfr); 69.539 + if(err) goto exit; 69.540 + err = pack_bool(conn->out, 1); 69.541 + if(err) goto exit; 69.542 + err = pack_sxpr(conn->out, mkint(vmid)); 69.543 + if(err) goto exit; 69.544 + err = pack_bool(conn->out, 0); 69.545 + if(err) goto exit; 69.546 + exit: 69.547 + return err; 69.548 +} 69.549 + 69.550 +int xfr_send_ok(Conn *conn, uint32_t vmid){ 69.551 + int err = 0; 69.552 + err = pack_type(conn->out, T_CONS); 69.553 + if(err) goto exit; 69.554 + err = pack_bool(conn->out, 1); 69.555 + if(err) goto exit; 69.556 + err = pack_sxpr(conn->out, oxfr_ok); 69.557 + if(err) goto exit; 69.558 + err = pack_bool(conn->out, 1); 69.559 + if(err) goto exit; 69.560 + err = pack_sxpr(conn->out, mkint(vmid)); 69.561 + if(err) goto exit; 69.562 + err = pack_bool(conn->out, 0); 69.563 + exit: 69.564 + return err; 69.565 +} 69.566 + 69.567 +int xfr_send_suspend(Conn *conn, uint32_t vmid){ 69.568 + int err = 0; 69.569 + 69.570 + err = pack_type(conn->out, T_CONS); 69.571 + if(err) goto exit; 69.572 + err = pack_bool(conn->out, 1); 69.573 + if(err) goto exit; 69.574 + err = pack_sxpr(conn->out, oxfr_suspend); 69.575 + if(err) goto exit; 69.576 + err = pack_bool(conn->out, 1); 69.577 + if(err) goto exit; 69.578 + err = pack_sxpr(conn->out, mkint(vmid)); 69.579 + if(err) goto exit; 69.580 + err = pack_bool(conn->out, 0); 69.581 + exit: 69.582 + return err; 69.583 +} 69.584 + 69.585 +/** Get vm state. Send transfer message. 69.586 + * 69.587 + * @param peer connection 69.588 + * @param msg message 69.589 + * @return 0 on success, error code otherwise 69.590 + */ 69.591 +int xfr_send_state(XfrState *state, Conn *xend, Conn *peer){ 69.592 + int err = 0; 69.593 + Sxpr sxpr; 69.594 + 69.595 + dprintf(">\n"); 69.596 + XfrState_set_state(state, XFR_STATE); 69.597 + // Send xfr message and the domain state. 69.598 + err = xfr_send_xfr(peer, state->vmid); 69.599 + if(err) goto exit; 69.600 + err = xen_domain_snd(xend, peer->out, state->vmid, state->vmconfig, state->vmconfig_n); 69.601 + if(err) goto exit; 69.602 + IOStream_flush(peer->out); 69.603 + // Read the response from the peer. 69.604 + err = unpack_sxpr(peer->in, &sxpr); 69.605 + if(err) goto exit; 69.606 + if(sxpr_elementp(sxpr, oxfr_err)){ 69.607 + // Error. 69.608 + int errcode; 69.609 + err = intof(sxpr_childN(sxpr, 0, ONONE), &errcode); 69.610 + if(!err) err = errcode; 69.611 + } else if(sxpr_elementp(sxpr, oxfr_ok)){ 69.612 + // Ok - get the new domain id. 69.613 + err = intof(sxpr_childN(sxpr, 0, ONONE), &state->vmid_new); 69.614 + xfr_error(peer, err); 69.615 + } else { 69.616 + // Anything else is invalid. But it may be too late. 69.617 + err = -EINVAL; 69.618 + xfr_error(peer, err); 69.619 + } 69.620 + exit: 69.621 + XfrState_set_err(state, err); 69.622 + dprintf("< err=%d\n", err); 69.623 + return err; 69.624 +} 69.625 + 69.626 +/** Finish the transfer. 69.627 + */ 69.628 +int xfr_send_done(XfrState *state, Conn *xend){ 69.629 + int err = 0; 69.630 + int first_err = 0; 69.631 + 69.632 + first_err = XfrState_first_err(state); 69.633 + if(first_err){ 69.634 + XfrState_set_state(state, XFR_FAIL); 69.635 + } else { 69.636 + XfrState_set_state(state, XFR_DONE); 69.637 + } 69.638 + if(first_err){ 69.639 + err = xfr_error(xend, first_err); 69.640 + } else { 69.641 + // Report new domain id to xend. 69.642 + err = xfr_send_ok(xend, state->vmid_new); 69.643 + } 69.644 + 69.645 + XfrState_set_err(state, err); 69.646 + if(XfrState_first_err(state)){ 69.647 + int s, serr; 69.648 + 69.649 + wprintf("> Transfer errors:\n"); 69.650 + for(s = 0; s < XFR_MAX; s++){ 69.651 + serr = state->state_err[s]; 69.652 + if(!serr) continue; 69.653 + wprintf("> state=%-12s err=%d\n", xfr_state_name(s), serr); 69.654 + } 69.655 + } else { 69.656 + wprintf("> Transfer OK\n"); 69.657 + } 69.658 + dprintf("< err=%d\n", err); 69.659 + return err; 69.660 +} 69.661 + 69.662 +/** Migrate a vm to another node. 69.663 + * 69.664 + * @param xend connection 69.665 + * @return 0 on success, error code otherwise 69.666 + */ 69.667 +int xfr_send(Args *args, XfrState *state, Conn *xend, uint32_t addr, uint32_t port){ 69.668 + int err = 0; 69.669 + Conn _peer = {}, *peer = &_peer; 69.670 + int flags = 0; 69.671 + struct in_addr xfr_addr; 69.672 + uint16_t xfr_port; 69.673 + time_t t0 = time(NULL), t1; 69.674 + 69.675 + dprintf(">\n"); 69.676 + flags |= CONN_NOBUFFER; 69.677 + if(args->compress){ 69.678 + flags |= CONN_WRITE_COMPRESS; 69.679 + } 69.680 + xfr_addr.s_addr = addr; 69.681 + xfr_port = port; 69.682 + if(!xfr_port) xfr_port = htons(XFRD_PORT); 69.683 + dprintf("> Xfr vmid=%u\n", state->vmid); 69.684 + dprintf("> Xfr xfr_addr=%s:%d\n", inet_ntoa(xfr_addr), ntohs(xfr_port)); 69.685 + err = Conn_connect(peer, flags, xfr_addr, xfr_port); 69.686 + if(err) goto exit; 69.687 + printf("\n"); 69.688 + XfrState_set_state(state, XFR_HELLO); 69.689 + // Send hello message. 69.690 + err = xfr_send_hello(peer); 69.691 + if(err) goto exit; 69.692 + printf("\n"); 69.693 + // Send vm state. 69.694 + err = xfr_send_state(state, xend, peer); 69.695 + if(err) goto exit; 69.696 + if(args->compress){ 69.697 + IOStream *zio = peer->out; 69.698 + int plain_bytes = lzi_stream_plain_bytes(zio); 69.699 + int comp_bytes = lzi_stream_comp_bytes(zio); 69.700 + float ratio = lzi_stream_ratio(zio); 69.701 + dprintf("> Compression: plain %d bytes, compressed %d bytes, ratio %3.2f\n", 69.702 + plain_bytes, comp_bytes, ratio); 69.703 + } 69.704 + printf("\n"); 69.705 + exit: 69