1 24 25 package com.mckoi.database; 26 27 import com.mckoi.store.*; 28 import com.mckoi.util.ByteArrayUtil; 29 import java.io.*; 30 import java.util.ArrayList ; 31 import com.mckoi.debug.DebugLogger; 32 33 41 42 class StateStore { 43 44 47 private int MAGIC = 0x0BAC8001; 48 49 52 private Store store; 53 54 57 private int table_id; 58 59 64 private MutableArea header_area; 65 66 69 private long vis_p; 70 71 74 private long del_p; 75 76 79 private ArrayList visible_list; 80 81 84 private ArrayList delete_list; 85 86 89 private boolean vis_list_change; 90 91 94 private boolean del_list_change; 95 96 99 public StateStore(Store store) { 100 this.store = store; 101 vis_list_change = false; 102 del_list_change = false; 103 } 104 105 106 109 private void removeResource(ArrayList list, String name) { 110 int sz = list.size(); 111 for (int i = 0; i < sz; ++i) { 112 StateResource resource = (StateResource) list.get(i); 113 if (name.equals(resource.name)) { 114 list.remove(i); 115 return; 116 } 117 } 118 throw new RuntimeException ("Couldn't find resource '" + name + "' in list."); 119 } 120 121 124 private void readStateResourceList(ArrayList list, long pointer) 125 throws IOException { 126 DataInputStream d_in = new DataInputStream( 127 store.getAreaInputStream(pointer)); 128 int version = d_in.readInt(); int count = (int) d_in.readLong(); 130 for (int i = 0; i < count; ++i) { 131 long table_id = d_in.readLong(); 132 String name = d_in.readUTF(); 133 StateResource resource = new StateResource(table_id, name); 134 list.add(resource); 135 } 136 d_in.close(); 137 } 138 139 142 private void writeStateResourceList(ArrayList list, DataOutputStream d_out) 143 throws IOException { 144 d_out.writeInt(1); 145 int sz = list.size(); 146 d_out.writeLong(sz); 147 for (int i = 0; i < sz; ++i) { 148 StateResource resource = (StateResource) list.get(i); 149 d_out.writeLong(resource.table_id); 150 d_out.writeUTF(resource.name); 151 } 152 } 153 154 158 private long writeListToStore(ArrayList list) throws IOException { 159 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 160 DataOutputStream d_out = new DataOutputStream(bout); 161 writeStateResourceList(list, d_out); 162 d_out.flush(); 163 d_out.close(); 164 165 byte[] buf = bout.toByteArray(); 166 167 AreaWriter a = store.createArea(buf.length); 168 long list_p = a.getID(); 169 a.put(buf); 170 a.finish(); 171 172 return list_p; 173 } 174 175 179 public synchronized long create() throws IOException { 180 AreaWriter vis_tables_area = store.createArea(12); 182 AreaWriter del_tables_area = store.createArea(12); 183 vis_p = vis_tables_area.getID(); 184 del_p = del_tables_area.getID(); 185 186 vis_tables_area.putInt(1); 188 vis_tables_area.putLong(0); 189 vis_tables_area.finish(); 190 del_tables_area.putInt(1); 191 del_tables_area.putLong(0); 192 del_tables_area.finish(); 193 194 AreaWriter header_writer = store.createArea(32); 196 long header_p = header_writer.getID(); 197 header_writer.putInt(MAGIC); 198 header_writer.putInt(0); 199 header_writer.putLong(0); 200 header_writer.putLong(vis_p); 201 header_writer.putLong(del_p); 202 header_writer.finish(); 203 204 header_area = store.getMutableArea(header_p); 205 206 table_id = 0; 208 209 visible_list = new ArrayList (); 210 delete_list = new ArrayList (); 211 212 return header_p; 214 } 215 216 220 public synchronized void init(long header_p) throws IOException { 221 header_area = store.getMutableArea(header_p); 222 int mag_value = header_area.getInt(); 223 if (mag_value != MAGIC) { 224 throw new IOException("Magic value for state header area is incorrect."); 225 } 226 if (header_area.getInt() != 0) { 227 throw new IOException("Unknown version for state header area."); 228 } 229 table_id = (int) header_area.getLong(); 230 vis_p = header_area.getLong(); 231 del_p = header_area.getLong(); 232 233 visible_list = new ArrayList (); 235 delete_list = new ArrayList (); 236 237 readStateResourceList(visible_list, vis_p); 239 readStateResourceList(delete_list, del_p); 240 241 } 242 243 248 public synchronized long convert(File legacy_sf, DebugLogger debug) 249 throws IOException { 250 long header_p = create(); 252 253 FixedSizeDataStore state_file = 255 new FixedSizeDataStore(legacy_sf, 507, debug); 256 state_file.open(true); 257 258 byte[] reserved_buffer = new byte[64]; 260 state_file.readReservedBuffer(reserved_buffer, 0, 64); 261 262 int tables_sector = ByteArrayUtil.getInt(reserved_buffer, 4); 264 InputStream sin = state_file.getSectorInputStream(tables_sector); 265 DataInputStream din = new DataInputStream(sin); 266 int vtver = din.readInt(); int size = din.readInt(); 268 for (int i = 0 ; i < size; ++i) { 270 int table_id = din.readInt(); 271 String resource_name = din.readUTF(); 272 if (!resource_name.startsWith(":")) { 274 resource_name = ":1" + resource_name; 275 } 276 addVisibleResource(new StateResource(table_id, resource_name)); 278 } 279 din.close(); 280 281 int dropped_sector = ByteArrayUtil.getInt(reserved_buffer, 12); 283 if (dropped_sector > -1) { 284 sin = state_file.getSectorInputStream(dropped_sector); 285 din = new DataInputStream(sin); 286 int dsver = din.readInt(); size = din.readInt(); 288 for (int i = 0; i < size; ++i) { 290 String resource_name = din.readUTF(); 291 if (!resource_name.startsWith(":")) { 293 resource_name = ":1" + resource_name; 294 } 295 addDeleteResource(new StateResource(-1, resource_name)); 297 } 298 din.close(); 299 300 } 301 302 int state_sector = ByteArrayUtil.getInt(reserved_buffer, 8); 304 sin = state_file.getSectorInputStream(state_sector); 305 din = new DataInputStream(sin); 306 din.readInt(); int conv_table_id = din.readInt(); 308 din.close(); 309 310 state_file.close(); 312 313 header_area.position(8); 315 header_area.putLong(conv_table_id); 316 header_area.checkOut(); 318 319 commit(); 321 322 return header_p; 324 } 325 326 329 public synchronized int nextTableID() throws IOException { 330 int cur_counter = table_id; 331 ++table_id; 332 333 try { 334 store.lockForWrite(); 335 336 header_area.position(8); 338 header_area.putLong(table_id); 339 header_area.checkOut(); 341 342 } 343 finally { 344 store.unlockForWrite(); 345 } 346 347 return cur_counter; 348 } 349 350 354 public synchronized StateResource[] getVisibleList() { 355 return (StateResource[]) 356 visible_list.toArray(new StateResource[visible_list.size()]); 357 } 358 359 363 public synchronized StateResource[] getDeleteList() { 364 return (StateResource[]) 365 delete_list.toArray(new StateResource[delete_list.size()]); 366 } 367 368 372 public synchronized boolean containsVisibleResource(int table_id) { 373 int sz = visible_list.size(); 374 for (int i = 0; i < sz; ++i) { 375 if (((StateResource) visible_list.get(i)).table_id == table_id) { 376 return true; 377 } 378 } 379 return false; 380 } 381 382 387 public synchronized void addVisibleResource(StateResource resource) { 388 visible_list.add(resource); 389 vis_list_change = true; 390 } 391 392 397 public synchronized void addDeleteResource(StateResource resource) { 398 delete_list.add(resource); 399 del_list_change = true; 400 } 401 402 407 public synchronized void removeVisibleResource(String name) { 408 removeResource(visible_list, name); 409 vis_list_change = true; 410 } 411 412 417 public synchronized void removeDeleteResource(String name) { 418 removeResource(delete_list, name); 419 del_list_change = true; 420 } 421 422 428 public synchronized boolean commit() throws IOException { 429 boolean changes = false; 430 long new_vis_p = vis_p; 431 long new_del_p = del_p; 432 433 try { 434 store.lockForWrite(); 435 436 if (vis_list_change) { 438 new_vis_p = writeListToStore(visible_list); 439 vis_list_change = false; 440 changes = true; 441 } 442 if (del_list_change) { 443 new_del_p = writeListToStore(delete_list); 444 del_list_change = false; 445 changes = true; 446 } 447 if (changes) { 449 header_area.position(16); 450 header_area.putLong(new_vis_p); 451 header_area.putLong(new_del_p); 452 header_area.checkOut(); 454 if (vis_p != new_vis_p) { 455 store.deleteArea(vis_p); 456 vis_p = new_vis_p; 457 } 458 if (del_p != new_del_p) { 459 store.deleteArea(del_p); 460 del_p = new_del_p; 461 } 462 } 463 464 } 465 finally { 466 store.unlockForWrite(); 467 } 468 469 return changes; 470 } 471 472 474 478 static class StateResource { 479 480 483 long table_id; 484 485 489 String name; 490 491 public StateResource(long table_id, String name) { 492 this.table_id = table_id; 493 this.name = name; 494 } 495 496 } 497 498 } 499 500 | Popular Tags |