Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1901740
  • 博文数量: 217
  • 博客积分: 4362
  • 博客等级: 上校
  • 技术积分: 4180
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-20 09:31
文章分类

全部博文(217)

文章存档

2017年(1)

2015年(2)

2014年(2)

2013年(6)

2012年(42)

2011年(119)

2010年(28)

2009年(17)

分类: Python/Ruby

2011-08-04 16:11:08

    有这样一个问题,我们要获取一个5900~65535之间的一个端口号。对于这个端口号必须是唯一出现的,不能重复,如果分配出去的端口号使用完了之后,还要进行相应的回收,等待下一次的分配。要使用erlang来实现,这个该如何实现呢?
    我是这么来实现的,在我的实现当中要使用mnesia数据库。每分配一个端口号出去之后,就将分配的端口号记录在数据库中,并且在数据库中使用一项记录下一次可以分配并且使用的端口号的值。如果下一次请求分配的时候,就直接读取分配出去的那个端口号,然后更新这一项,往数据库中添加已经分配的这个端口号,等下一次如果再次分配的时候,就直接分配。
    我的程序代码如下:
  1. %% vncport.erl
  2. %% Author: Sunny
  3. %% Created: 2011-7-25
  4. %% Description: get vncport
  5. -module(vncport).
  6. -date("2011.07.25").

  7. %%
  8. %% Include Files
  9. %%
  10. -include_lib("stdlib/include/qlc.hrl").
  11. -record(vnc_counter,
  12.                 {
  13.                 vncport_num,
  14.                 used_flag
  15.                 }).

  16. %%
  17. %% Exported Functions
  18. %%
  19. -export([init/0, stop/0]).
  20. -export([recovery_one_vncport/1]).
  21. -export([get_next_vncport/0]).

  22. %%
  23. %% Api Functions
  24. %%
  25. init() ->
  26.      mnesia:stop(),
  27.      mnesia:delete_schema([node()]),
  28.      mnesia:create_schema([node()]),
  29.      mnesia:start(),
  30.      mnesia:create_table(vnc_counter,[{attributes, record_info(fields, vnc_counter)}]),
  31.      F = fun(N) ->
  32.              insert_to_table(N)
  33.          end,
  34.      for(5908, 5910, F),
  35.      for(5915, 5917, F),
  36.      mnesia:dirty_update_counter(vnc_counter, mac_id, 5900).

  37. stop() ->
  38.     mnesia:stop().

  39. get_next_vncport() ->
  40.     Query = qlc:q([X#vnc_counter.used_flag || X <- mnesia:table(vnc_counter),
  41.                     X#vnc_counter.vncport_num =:= mac_id]),
  42.     F = fun() ->
  43.             qlc:e(Query)
  44.     end,
  45.     io:format("get the vncport which is not used~n"), %% degug info
  46.     {atomic, [Result]} = mnesia:transaction(F),
  47. %    spawn(fun() -> update_vnc_counter(Result) end),
  48.     update_vnc_counter(Result),
  49.     io:format("get the next vncport is:~p~n", [Result]), %% debug info
  50.     Result.

  51. recovery_one_vncport(N) ->
  52.     Row = {vnc_counter, N},
  53.     F = fun() ->
  54.         mnesia:delete(Row)
  55.     end,
  56.     Result = mnesia:transaction(F),
  57.     io:format("delete ~p successfully~n", [N]), %% debug info
  58.     Result.

  59. %%
  60. %% Local Functions
  61. %%
  62. update_vnc_counter(X) ->
  63.     io:format("spawn one process to update vnc_counter~n"), %% debug info
  64.     insert_to_table(X),
  65.     io:format("add one used vncport to vnc_counter successfully!~n"), %% debug info
  66.     if
  67.         X+1 > 65535 ->
  68.             N=5900;
  69.         X+1 =< 65535 ->
  70.             N=X+1
  71.     end,
  72.     io:format("now begin check whether in vnc_counter~n"), %% debug info
  73.     case check_in_vnc_counter(N) of
  74.         true ->
  75.             io:format("find ~p is in vnc_counter~n", [N]), %% debug info
  76.             NX = find_not_in_vnc_counter(N), %% find one not in vnc_counter
  77.             Row = #vnc_counter{vncport_num=mac_id, used_flag=NX};
  78.         false ->
  79.             io:format("find ~p is not in vnc_counter~n", [N]), %% debug info
  80.             Row = #vnc_counter{vncport_num=mac_id, used_flag=N}
  81.     end,
  82.     F = fun() ->
  83.             mnesia:write(Row)
  84.         end,
  85.     mnesia:transaction(F),
  86.     io:format("update vnc_counter over~n"), %% debug info
  87.     ok.

  88. check_in_vnc_counter(N) ->
  89.     io:format("check ~p is or not in vnc_counter~n", [N]), %% debug info
  90.     Query = qlc:q([X#vnc_counter.vncport_num || X <- mnesia:table(vnc_counter),
  91.                     X#vnc_counter.vncport_num =:= N]),
  92.     F = fun() ->
  93.             qlc:e(Query)
  94.     end,
  95.     Result = mnesia:transaction(F),
  96.     io:format("check result is:~p~n", [Result]), %% debug info
  97.     case Result of
  98.         {atomic, []} ->
  99.             Return = false;
  100.         {atomic, [_]} ->
  101.             Return = true
  102.     end,
  103.     Return.

  104. find_not_in_vnc_counter(N) ->
  105.     if
  106.         N+1 > 65535 ->
  107.             NX = 5900;
  108.         N+1 =< 65535 ->
  109.             NX = N+1
  110.     end,
  111.     case check_in_vnc_counter(NX) of
  112.         true ->
  113.             Result = find_not_in_vnc_counter(N+1);
  114.         false ->
  115.             Result = NX
  116.     end,
  117.     Result.

  118. insert_to_table(N) ->
  119.     Row = #vnc_counter{vncport_num=N, used_flag=yes},
  120.     F = fun() ->
  121.             mnesia:write(Row)
  122.         end,
  123.     mnesia:transaction(F).

  124. for(Max, Max, F) ->
  125.     [F(Max)];
  126. for(Min, Max, F) ->
  127.     [F(Min)|for(Min+1, Max, F)].
    这个程序的执行结果是:
  1. 1> c(vncport).
  2. {ok,vncport}
  3. 2> vncport:init().
  4. 5900
  5. 3> vncport:get_next_vncport().
  6. get the vncport which is not used
  7. spawn one process to update vnc_counter
  8. add one used vncport to vnc_counter
  9. now begin check whether in vnc_counter
  10. check 5901 is or not in vnc_counter
  11. check result is:{atomic,[]}
  12. find 5901 is not in vnc_counter
  13. update vnc_counter over
  14. get the next vncport is:5900
  15. 5900
  16. 4> vncport:get_next_vncport().
  17. get the vncport which is not used
  18. spawn one process to update vnc_counter
  19. add one used vncport to vnc_counter
  20. now begin check whether in vnc_counter
  21. check 5902 is or not in vnc_counter
  22. check result is:{atomic,[5902]}
  23. find 5902 is in vnc_counter
  24. check 5903 is or not in vnc_counter
  25. check result is:{atomic,[5903]}
  26. check 5904 is or not in vnc_counter
  27. check result is:{atomic,[5904]}
  28. check 5905 is or not in vnc_counter
  29. check result is:{atomic,[5905]}
  30. check 5906 is or not in vnc_counter
  31. check result is:{atomic,[5906]}
  32. check 5907 is or not in vnc_counter
  33. check result is:{atomic,[5907]}
  34. check 5908 is or not in vnc_counter
  35. check result is:{atomic,[5908]}
  36. check 5909 is or not in vnc_counter
  37. check result is:{atomic,[5909]}
  38. check 5910 is or not in vnc_counter
  39. check result is:{atomic,[5910]}
  40. check 5911 is or not in vnc_counter
  41. check result is:{atomic,[]}
  42. update vnc_counter over
  43. get the next vncport is:5901
  44. 5901
  45. 5> vncport:get_next_vncport().
  46. get the vncport which is not used
  47. spawn one process to update vnc_counter
  48. add one used vncport to vnc_counter
  49. now begin check whether in vnc_counter
  50. check 5912 is or not in vnc_counter
  51. check result is:{atomic,[]}
  52. find 5912 is not in vnc_counter
  53. update vnc_counter over
  54. get the next vncport is:5911
  55. 5911
  56. 6> vncport:get_next_vncport().
  57. get the vncport which is not used
  58. spawn one process to update vnc_counter
  59. add one used vncport to vnc_counter
  60. now begin check whether in vnc_counter
  61. check 5913 is or not in vnc_counter
  62. check result is:{atomic,[5913]}
  63. find 5913 is in vnc_counter
  64. check 5914 is or not in vnc_counter
  65. check result is:{atomic,[5914]}
  66. check 5915 is or not in vnc_counter
  67. check result is:{atomic,[5915]}
  68. check 5916 is or not in vnc_counter
  69. check result is:{atomic,[5916]}
  70. check 5917 is or not in vnc_counter
  71. check result is:{atomic,[5917]}
  72. check 5918 is or not in vnc_counter
  73. check result is:{atomic,[]}
  74. update vnc_counter over
  75. get the next vncport is:5912
  76. 5912
  77. 7> vncport:get_next_vncport().
  78. get the vncport which is not used
  79. spawn one process to update vnc_counter
  80. add one used vncport to vnc_counter
  81. now begin check whether in vnc_counter
  82. check 5919 is or not in vnc_counter
  83. check result is:{atomic,[]}
  84. find 5919 is not in vnc_counter
  85. update vnc_counter over
  86. get the next vncport is:5918
  87. 5918
  88. 8> vncport:get_next_vncport().
  89. get the vncport which is not used
  90. spawn one process to update vnc_counter
  91. add one used vncport to vnc_counter
  92. now begin check whether in vnc_counter
  93. check 5920 is or not in vnc_counter
  94. check result is:{atomic,[]}
  95. find 5920 is not in vnc_counter
  96. update vnc_counter over
  97. get the next vncport is:5919
  98. 5919
  99. 9> vncport:get_next_vncport().
  100. get the vncport which is not used
  101. spawn one process to update vnc_counter
  102. add one used vncport to vnc_counter
  103. now begin check whether in vnc_counter
  104. check 5921 is or not in vnc_counter
  105. check result is:{atomic,[]}
  106. find 5921 is not in vnc_counter
  107. update vnc_counter over
  108. get the next vncport is:5920
  109. 5920
  110. 10>
    可能输出的信息比较多些,但是对于本程序来说我们只要关注最后的那个数据就行了。
    在我的程序中有一个小的技巧就是在init()函数中使用的
    mnesia:dirty_update_counter(vnc_counter, mac_id, 5900),
    我使用了这个来记录下一次要读取的可以使用的数据,原先使用文件的记录,发现那是有问题的,而且在程序中处理数据库可以使用spawn一个进程,这个是可以的,但是我不知道使用是不是一件好的事情。
阅读(1200) | 评论(0) | 转发(0) |
0

上一篇:erlang 进制转换

下一篇:标准I/O的三种缓冲

给主人留下些什么吧!~~