PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/castoro-gateway/ext/test/cache_spec.rb

http://github.com/ToshiyukiTerashita/castoro
Ruby | 462 lines | 361 code | 83 blank | 18 comment | 34 complexity | 09df81b40b16dc6b38942fd84f8bc577 MD5 | raw file
Possible License(s): LGPL-3.0
  1. #
  2. # Copyright 2010 Ricoh Company, Ltd.
  3. #
  4. # This file is part of Castoro.
  5. #
  6. # Castoro is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Lesser General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Castoro is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public License
  17. # along with Castoro. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. require File.join(File.dirname(__FILE__), '../cache.so')
  20. PEER1 = "std100"; BASE1="/expdsk/baskets/r"
  21. PEER2 = "std101"; BASE2="/expdsk/baskets/w"
  22. PEER3 = "std102"; BASE3="/expdsk/baskets/a"
  23. ACTIVE = { :status => Castoro::Cache::Peer::ACTIVE, :available => 10*1000*1000*1000 }
  24. ACTIVE_100 = { :status => Castoro::Cache::Peer::ACTIVE, :available => 100 }
  25. ACTIVE_1000 = { :status => Castoro::Cache::Peer::ACTIVE, :available => 1000 }
  26. READONLY = { :status => Castoro::Cache::Peer::READONLY }
  27. MAINTENANCE = { :status => Castoro::Cache::Peer::MAINTENANCE }
  28. def buildpath(p, b, c, t, r)
  29. k = c / 1000
  30. m, k = k.divmod 1000
  31. g, m = m.divmod 1000
  32. "%s:%s/%d/%03d/%03d/%d.%d.%d"%[p, b, g, m, k, c, t, r]
  33. end
  34. def nfs1(c, t, r); buildpath PEER1, BASE1, c, t, r; end
  35. def nfs2(c, t, r); buildpath PEER2, BASE2, c, t, r; end
  36. def nfs3(c, t, r); buildpath PEER3, BASE3, c, t, r; end
  37. def check_range this, id, expr
  38. this.peers[PEER1].insert(id,0,0,BASE1)
  39. this.find(id,0,0)[0].should =~ expr
  40. this.peers[PEER1].insert(id+999,0,0,BASE1)
  41. this.find(id+999,0,0)[0].should =~ expr
  42. end
  43. describe Castoro::Cache do
  44. context "when initialize" do
  45. it "should be raise exception when page = 0" do
  46. lambda{ c = Castoro::Cache.new(0) }.should raise_error(ArgumentError)
  47. end
  48. it "should be raise exception when pages < 0" do
  49. lambda{ c = Castoro::Cache.new(-1) }.should raise_error(ArgumentError)
  50. end
  51. it "should be success when pages >0" do
  52. Castoro::Cache.new(1).should_not be_nil
  53. end
  54. end
  55. context "when empty" do
  56. before do
  57. @cache = Castoro::Cache.new(10)
  58. end
  59. it "should be empty" do
  60. @cache.find(1,2,3).should be_empty
  61. end
  62. after do
  63. @cache = nil
  64. end
  65. end
  66. context "when insert a item" do
  67. before do
  68. @cache = Castoro::Cache.new(10)
  69. @cache.peers[PEER1].insert(1,2,3,BASE1)
  70. end
  71. it "should be empty when insert and remove it" do
  72. @cache.peers[PEER1].erase(1,2,3)
  73. @cache.find(1,2,3).should be_empty
  74. end
  75. it "should be empty when insert but NOT activated" do
  76. @cache.find(1,2,3).should be_empty
  77. end
  78. it "should be one item when mark active" do
  79. @cache.peers[PEER1].status = ACTIVE
  80. @cache.find(1,2,3).should == [nfs1(1,2,3)]
  81. end
  82. it "should be one item when mark readonly" do
  83. @cache.peers[PEER1].status = READONLY
  84. @cache.find(1,2,3).should == [nfs1(1,2,3)]
  85. end
  86. it "should be empty when mark maintenance" do
  87. @cache.peers[PEER1].status = MAINTENANCE
  88. @cache.find(1,2,3).should be_empty
  89. end
  90. after do
  91. @cache = nil
  92. end
  93. end
  94. context "when insert 2 items into same peer" do
  95. before do
  96. @cache = Castoro::Cache.new(10)
  97. @cache.peers[PEER1].insert(1,2,3,BASE1)
  98. @cache.peers[PEER1].insert(4,5,6,BASE1)
  99. end
  100. it "should be empty when insert, but NOT activated" do
  101. @cache.find(1,2,3).should be_empty
  102. @cache.find(4,5,6).should be_empty
  103. end
  104. it "should be one item when and mark active" do
  105. @cache.peers[PEER1].status = ACTIVE
  106. @cache.find(1,2,3).should == [nfs1(1,2,3)]
  107. @cache.find(4,5,6).should == [nfs1(4,5,6)]
  108. end
  109. it "should be empty when mark readonly" do
  110. @cache.peers[PEER1].status = READONLY
  111. @cache.find(1,2,3).should == [nfs1(1,2,3)]
  112. @cache.find(4,5,6).should == [nfs1(4,5,6)]
  113. end
  114. it "should be empty when mark maintenance" do
  115. @cache.peers[PEER1].status = MAINTENANCE
  116. @cache.find(1,2,3).should be_empty
  117. @cache.find(4,5,6).should be_empty
  118. end
  119. after do
  120. @cache = nil
  121. end
  122. end
  123. context "when insert 2 items into different peers" do
  124. before do
  125. @cache = Castoro::Cache.new(10)
  126. @cache.peers[PEER1].insert(1,2,3,BASE1)
  127. @cache.peers[PEER2].insert(1,2,3,BASE2)
  128. end
  129. it "should be empty when insert, but NOT activated" do
  130. @cache.find(1,2,3).should be_empty
  131. end
  132. it "should be one item when mark active one" do
  133. @cache.peers[PEER1].status = ACTIVE
  134. @cache.find(1,2,3).should == [nfs1(1,2,3)]
  135. end
  136. context "-> activated" do
  137. before do
  138. @cache.peers[PEER1].status = ACTIVE
  139. @cache.peers[PEER2].status = ACTIVE
  140. end
  141. it "should be two items mark active all" do
  142. @cache.find(1,2,3).should == [nfs1(1,2,3),nfs2(1,2,3)]
  143. end
  144. it "should be empty when mark readonly" do
  145. @cache.peers[PEER1].status = READONLY
  146. @cache.find(1,2,3).should == [nfs1(1,2,3),nfs2(1,2,3)]
  147. @cache.peers[PEER2].status = READONLY
  148. @cache.find(1,2,3).should == [nfs1(1,2,3),nfs2(1,2,3)]
  149. end
  150. it "should be empty when mark maintenance" do
  151. @cache.peers[PEER1].status = MAINTENANCE
  152. @cache.find(1,2,3).should == [nfs2(1,2,3)]
  153. @cache.peers[PEER2].status = MAINTENANCE
  154. @cache.find(1,2,3).should be_empty
  155. end
  156. end
  157. after do
  158. @cache = nil
  159. end
  160. end
  161. context "when remove item" do
  162. before do
  163. @cache = Castoro::Cache.new(10)
  164. @cache.peers[PEER1].insert(1,2,3,BASE1)
  165. @cache.peers[PEER2].insert(1,2,3,BASE2)
  166. @cache.peers[PEER3].insert(1,2,3,BASE3)
  167. @cache.peers[PEER1].status = ACTIVE
  168. @cache.peers[PEER2].status = ACTIVE
  169. @cache.peers[PEER3].status = ACTIVE
  170. @cache.peers[PEER1].insert(2,2,3,BASE1)
  171. end
  172. it "should be found 3 peers when remove unknown item" do
  173. @cache.peers["unknown"].erase(1,2,3)
  174. @cache.find(1,2,3).should == [nfs1(1,2,3),nfs2(1,2,3),nfs3(1,2,3)]
  175. end
  176. it "should be found 2 peer when remove 1 item" do
  177. @cache.peers[PEER3].erase(1,2,3)
  178. @cache.find(1,2,3).should == [nfs1(1,2,3),nfs2(1,2,3)]
  179. end
  180. it "should be found 2 peer when remove 1 item" do
  181. @cache.peers[PEER2].erase(1,2,3)
  182. @cache.peers[PEER3].erase(1,2,3)
  183. @cache.find(1,2,3).should == [nfs1(1,2,3)]
  184. end
  185. it "should be found no peers when remove all." do
  186. @cache.peers[PEER1].erase(1,2,3)
  187. @cache.peers[PEER2].erase(1,2,3)
  188. @cache.peers[PEER3].erase(1,2,3)
  189. @cache.find(1,2,3).should == nil
  190. end
  191. after do
  192. @cache = nil
  193. end
  194. end
  195. context "peers matching" do
  196. before do
  197. @cache = Castoro::Cache.new(10)
  198. end
  199. it "should empty when there is no peers." do
  200. @cache.peers.find(0).should be_empty
  201. end
  202. context "there is 2 peers, there are 100 and 1000 bytes writable" do
  203. before do
  204. @cache.peers[PEER1].status = ACTIVE_100
  205. @cache.peers[PEER2].status = ACTIVE_1000
  206. end
  207. it "should be include 2(all) peers when argument is omitted" do
  208. @cache.peers.find.should == [PEER1, PEER2]
  209. end
  210. it "should be include 2 peers when require 50 bytes" do
  211. @cache.peers.find(50).should == [PEER1, PEER2]
  212. end
  213. it "should be include 1 peers when require 500 bytes" do
  214. @cache.peers.find(500).should == [PEER2]
  215. end
  216. it "should empty when require 5000 bytes" do
  217. @cache.peers.find(5000).should be_empty
  218. end
  219. end
  220. context "there is 2 peers, there are 100 bytes writable and 1000 bytes avail but readonly" do
  221. before do
  222. @cache.peers[PEER1].status = ACTIVE_100
  223. @cache.peers[PEER2].status = ACTIVE_1000
  224. @cache.peers[PEER2].status = READONLY
  225. end
  226. it "should be include 2(all) peers when argument is omitted" do
  227. @cache.peers.find.should == [PEER1, PEER2]
  228. end
  229. it "should be include 1 peer when require 50 bytes" do
  230. @cache.peers.find(50).should == [PEER1]
  231. end
  232. it "should empty when be include 1 peers when require 500 bytes" do
  233. @cache.peers.find(500).should be_empty
  234. end
  235. it "should empty when require 5000 bytes" do
  236. @cache.peers.find(5000).should be_empty
  237. end
  238. end
  239. after do
  240. @cache = nil
  241. end
  242. end
  243. context "when content id is large" do
  244. before do
  245. @cache = Castoro::Cache.new(10)
  246. @cache.peers[PEER1].status = ACTIVE
  247. end
  248. it "part of path should be '/0/000/000/' when id < 1000" do
  249. check_range @cache, 0, %r{/0/000/000/}
  250. end
  251. it "part of path should be '/0/000/001/' when 1000<= id <=1999" do
  252. check_range @cache, 1*1000, %r{/0/000/001/}
  253. end
  254. it "part of path should be '/0/000/999/' when 999,000<= id <=999,999" do
  255. check_range @cache, 999*1000, %r{/0/000/999/}
  256. end
  257. it "part of path should be '/0/001/000/' when 1,000,000<= id <=1,000,999" do
  258. check_range @cache, 1*1000*1000, %r{/0/001/000/}
  259. end
  260. it "part of path should be '/0/999/000/' when 999,000,000<= id <=999,000,999" do
  261. check_range @cache, 999*1000*1000, %r{/0/999/000/}
  262. end
  263. it "part of path should be '/1/000/000/' when 1,000,000,000<= id <=1,000,000,999" do
  264. check_range @cache, 1*1000*1000*1000, %r{/1/000/000/}
  265. end
  266. it "part of path should be '/1000/000/000/' when 1,000,000,000,000<= id <=1,000,000,000,999" do
  267. check_range @cache, 1000*1000*1000*1000, %r{/1000/000/000/}
  268. end
  269. after do
  270. @cache = nil
  271. end
  272. end
  273. context "when make_nfs_path is overloaded" do
  274. before do
  275. @cache = Castoro::Cache.new(10)
  276. @cache.peers[PEER1].status = ACTIVE
  277. class << @cache
  278. def make_nfs_path(p, b, c, t, r)
  279. {:host=>p.to_s, :path=>"#{b}/#{c}.#{t}@#{r}"}
  280. end
  281. end
  282. end
  283. it "path should be 'peer:/base/cid.type@rev'" do
  284. @cache.peers[PEER1].insert(1,2,3,BASE1)
  285. @cache.find(1,2,3).should == [{:host=>PEER1, :path=>"#{BASE1}/1.2@3"}]
  286. end
  287. after do
  288. @cache = nil
  289. end
  290. end
  291. context "watchdog expires" do
  292. before do
  293. @cache = Castoro::Cache.new(10)
  294. @cache.watchdog_limit = 1
  295. @cache.peers[PEER1].insert(1,2,3,BASE1)
  296. @cache.peers[PEER2].insert(1,2,3,BASE2)
  297. end
  298. it "should be include peer1, peer2" do
  299. @cache.peers[PEER1].status = ACTIVE
  300. @cache.peers[PEER2].status = ACTIVE
  301. @cache.find(1,2,3).should == [nfs1(1,2,3),nfs2(1,2,3)]
  302. end
  303. it "should not be include peer1 when timeout" do
  304. @cache.peers[PEER1].status = ACTIVE
  305. @cache.peers[PEER2].status = ACTIVE
  306. sleep 2.0
  307. @cache.peers[PEER2].status = ACTIVE
  308. @cache.find(1,2,3).should == [nfs2(1,2,3)]
  309. end
  310. describe "#watchdog_limit" do
  311. it "should be eql 1" do
  312. @cache.watchdog_limit.should be_eql 1
  313. end
  314. end
  315. after do
  316. @cache = nil
  317. end
  318. end
  319. context "dump cache" do
  320. before do
  321. @cache = Castoro::Cache.new(10)
  322. @cache.peers[PEER1].insert(1,2,3,BASE1)
  323. @cache.peers[PEER2].insert(1,2,3,BASE2)
  324. @cache.peers[PEER3].insert(1,2,3,BASE3)
  325. @cache.peers[PEER1].status = ACTIVE
  326. @cache.peers[PEER2].status = READONLY
  327. @cache.peers[PEER3].status = MAINTENANCE
  328. end
  329. it "should be dump" do
  330. result = ""
  331. class << result
  332. def puts(str)
  333. self << str + "\n"
  334. end
  335. end
  336. @cache.dump(result).should be_true
  337. result.should == <<__RESULT__
  338. std100: /expdsk/baskets/r/1.2.3
  339. std101: /expdsk/baskets/w/1.2.3
  340. std102: /expdsk/baskets/a/1.2.3
  341. __RESULT__
  342. end
  343. after do
  344. @cache = nil
  345. end
  346. end
  347. context "cache stat" do
  348. before do
  349. @cache = Castoro::Cache.new(10)
  350. @cache.watchdog_limit = 5
  351. @cache.peers[PEER1].insert(1,2,3,BASE1)
  352. @cache.peers[PEER2].insert(1,2,3,BASE2)
  353. @cache.peers[PEER1].status = ACTIVE
  354. @cache.peers[PEER2].status = READONLY
  355. @cache.find(1,2,3)
  356. @cache.find(4,5,6)
  357. end
  358. describe "#watchdog_limit" do
  359. it "should be eql 1" do
  360. @cache.watchdog_limit.should be_eql 5
  361. end
  362. end
  363. it "should return stats" do
  364. @cache.stat(Castoro::Cache::DSTAT_CACHE_EXPIRE).should == 5
  365. @cache.stat(Castoro::Cache::DSTAT_CACHE_REQUESTS).should == 2
  366. @cache.stat(Castoro::Cache::DSTAT_CACHE_HITS).should == 1
  367. @cache.stat(Castoro::Cache::DSTAT_CACHE_COUNT_CLEAR).should == 500
  368. @cache.stat(Castoro::Cache::DSTAT_ALLOCATE_PAGES).should == 10
  369. @cache.stat(Castoro::Cache::DSTAT_FREE_PAGES).should == 9
  370. @cache.stat(Castoro::Cache::DSTAT_ACTIVE_PAGES).should == 1
  371. @cache.stat(Castoro::Cache::DSTAT_HAVE_STATUS_PEERS).should == 2
  372. @cache.stat(Castoro::Cache::DSTAT_ACTIVE_PEERS).should == 1
  373. @cache.stat(Castoro::Cache::DSTAT_READABLE_PEERS).should == 2
  374. end
  375. after do
  376. @cache = nil
  377. end
  378. end
  379. end