1 21 22 package org.apache.derby.impl.store.access; 23 24 import org.apache.derby.iapi.reference.Attribute; 25 import org.apache.derby.iapi.reference.Property; 26 import org.apache.derby.iapi.reference.SQLState; 27 28 import org.apache.derby.iapi.types.UserType; 29 import org.apache.derby.impl.store.access.UTF; 30 import org.apache.derby.impl.store.access.UTFQualifier; 31 import org.apache.derby.iapi.services.io.FormatableBitSet; 32 import org.apache.derby.iapi.services.io.FormatableHashtable; 33 import org.apache.derby.iapi.services.locks.ShExLockable; 34 import org.apache.derby.iapi.services.locks.ShExQual; 35 import org.apache.derby.iapi.services.daemon.Serviceable; 36 import org.apache.derby.iapi.services.locks.C_LockFactory; 37 import org.apache.derby.iapi.services.locks.Latch; 38 import org.apache.derby.iapi.services.locks.LockFactory; 39 import org.apache.derby.iapi.services.property.PropertyUtil; 40 41 import org.apache.derby.iapi.services.monitor.Monitor; 42 import org.apache.derby.iapi.services.sanity.SanityManager; 43 import org.apache.derby.iapi.services.io.Formatable; 44 import org.apache.derby.iapi.error.StandardException; 45 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 46 import org.apache.derby.iapi.store.access.conglomerate.TransactionManager; 47 import org.apache.derby.iapi.store.access.AccessFactory; 48 import org.apache.derby.iapi.store.access.AccessFactoryGlobals; 49 import org.apache.derby.iapi.store.access.ConglomerateController; 50 import org.apache.derby.iapi.services.property.PropertyFactory; 51 import org.apache.derby.iapi.services.property.PropertySetCallback; 52 import org.apache.derby.iapi.store.access.Qualifier; 53 import org.apache.derby.iapi.store.access.ScanController; 54 import org.apache.derby.iapi.store.access.TransactionController; 55 import org.apache.derby.iapi.store.raw.RawStoreFactory; 56 import org.apache.derby.iapi.types.DataValueDescriptor; 57 58 import java.io.Serializable ; 59 import java.util.Dictionary ; 60 import java.util.Enumeration ; 61 import java.util.Hashtable ; 62 import java.util.Properties ; 63 64 97 class PropertyConglomerate 98 { 99 protected long propertiesConglomId; 100 protected Properties serviceProperties; 101 private LockFactory lf; 102 private Dictionary cachedSet; 103 private CacheLock cachedLock; 104 105 private PropertyFactory pf; 106 107 108 109 PropertyConglomerate( 110 TransactionController tc, 111 boolean create, 112 Properties serviceProperties, 113 PropertyFactory pf) 114 throws StandardException 115 { 116 this.pf = pf; 117 118 if (!create) { 119 String id = serviceProperties.getProperty(Property.PROPERTIES_CONGLOM_ID); 120 if (id == null) { 121 create = true; 122 } else { 123 try { 124 propertiesConglomId = Long.valueOf(id).longValue(); 125 } catch (NumberFormatException nfe) { 126 throw Monitor.exceptionStartingModule(nfe) ; 127 } 128 } 129 } 130 131 if (create) { 132 DataValueDescriptor[] template = makeNewTemplate(); 133 134 Properties conglomProperties = new Properties (); 135 136 conglomProperties.put( 137 Property.PAGE_SIZE_PARAMETER, 138 RawStoreFactory.PAGE_SIZE_STRING); 139 140 conglomProperties.put( 141 RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, 142 RawStoreFactory.PAGE_RESERVED_ZERO_SPACE_STRING); 143 144 propertiesConglomId = 145 tc.createConglomerate( 146 AccessFactoryGlobals.HEAP, 147 template, 148 null, 149 conglomProperties, 150 TransactionController.IS_DEFAULT); 151 152 serviceProperties.put( 153 Property.PROPERTIES_CONGLOM_ID, 154 Long.toString(propertiesConglomId)); 155 } 156 157 this.serviceProperties = serviceProperties; 158 159 lf = ((RAMTransaction) tc).getAccessManager().getLockFactory(); 160 cachedLock = new CacheLock(this); 161 162 PC_XenaVersion softwareVersion = new PC_XenaVersion(); 163 if (create) 164 setProperty(tc,DataDictionary.PROPERTY_CONGLOMERATE_VERSION, 165 softwareVersion, true); 166 else 167 softwareVersion.upgradeIfNeeded(tc,this,serviceProperties); 168 169 getCachedDbProperties(tc); 170 } 171 172 173 174 177 private DataValueDescriptor[] makeNewTemplate(String key, Serializable value) 178 { 179 DataValueDescriptor[] template = new DataValueDescriptor[2]; 180 181 template[0] = new UTF(key); 182 template[1] = new UserType(value); 183 184 return(template); 185 } 186 187 190 private DataValueDescriptor[] makeNewTemplate() 191 { 192 DataValueDescriptor[] template = new DataValueDescriptor[2]; 193 194 template[0] = new UTF(); 195 template[1] = new UserType(); 196 197 return(template); 198 } 199 200 215 private ScanController openScan( 216 TransactionController tc, 217 String key, 218 int open_mode) 219 throws StandardException 220 { 221 Qualifier[][] qualifiers = null; 222 223 if (key != null) { 224 qualifiers = new Qualifier[1][]; 226 qualifiers[0] = new Qualifier[1]; 227 qualifiers[0][0] = new UTFQualifier(0, key); 228 } 229 230 ScanController scan = 232 tc.openScan( 233 propertiesConglomId, 234 false, open_mode, 236 TransactionController.MODE_TABLE, 237 TransactionController.ISOLATION_SERIALIZABLE, 238 (FormatableBitSet) null, 239 (DataValueDescriptor[]) null, ScanController.NA, 241 qualifiers, 242 (DataValueDescriptor[]) null, ScanController.NA); 244 245 return(scan); 246 } 247 248 249 256 257 261 void setPropertyDefault(TransactionController tc, String key, Serializable value) 262 throws StandardException 263 { 264 lockProperties(tc); 265 Serializable valueToSave = null; 266 if (propertyDefaultIsVisible(tc,key)) 270 { 271 valueToSave = validateApplyAndMap(tc,key,value,false); 272 } 273 else 274 { 275 synchronized (this) { 276 Hashtable defaults = new Hashtable(); 277 getProperties(tc,defaults,false,true); 278 validate(key,value,defaults); 279 valueToSave = map(key,value,defaults); 280 } 281 } 282 savePropertyDefault(tc,key,valueToSave); 283 } 284 285 boolean propertyDefaultIsVisible(TransactionController tc,String key) throws StandardException 286 { 287 lockProperties(tc); 288 return(readProperty(tc,key) == null); 289 } 290 291 void saveProperty(TransactionController tc, String key, Serializable value) 292 throws StandardException 293 { 294 if (saveServiceProperty(key,value)) return; 295 296 ScanController scan = 298 this.openScan(tc, key, TransactionController.OPENMODE_FORUPDATE); 299 300 DataValueDescriptor[] row = makeNewTemplate(); 301 302 if (scan.fetchNext(row)) 303 { 304 if (value == null) 305 { 306 308 scan.delete(); 309 } 310 else 311 { 312 314 row[1] = new UserType(value); 315 316 scan.replace(row, (FormatableBitSet) null); 317 } 318 319 scan.close(); 320 } 321 else 322 { 323 325 scan.close(); 326 scan = null; 327 328 if (value != null) 329 { 330 332 row = makeNewTemplate(key, value); 333 334 ConglomerateController cc = 335 tc.openConglomerate( 336 propertiesConglomId, 337 false, 338 TransactionController.OPENMODE_FORUPDATE, 339 TransactionController.MODE_TABLE, 340 TransactionController.ISOLATION_SERIALIZABLE); 341 342 cc.insert(row); 343 344 cc.close(); 345 } 346 } 347 } 348 349 private boolean saveServiceProperty(String key, Serializable value) 350 { 351 if (PropertyUtil.isServiceProperty(key)) 352 { 353 if (value != null) 354 serviceProperties.put(key, value); 355 else 356 serviceProperties.remove(key); 357 return true; 358 } 359 else 360 { 361 return false; 362 } 363 } 364 365 void savePropertyDefault(TransactionController tc, String key, Serializable value) 366 throws StandardException 367 { 368 if (saveServiceProperty(key,value)) return; 369 370 Dictionary defaults = (Dictionary)readProperty(tc,AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); 371 if (defaults == null) defaults = new FormatableHashtable(); 372 if (value==null) 373 defaults.remove(key); 374 else 375 defaults.put(key,value); 376 if (defaults.size() == 0) defaults = null; 377 saveProperty(tc,AccessFactoryGlobals.DEFAULT_PROPERTY_NAME,(Serializable )defaults); 378 } 379 380 private Serializable validateApplyAndMap(TransactionController tc, 381 String key, Serializable value, boolean dbOnlyProperty) 382 throws StandardException 383 { 384 Dictionary d = new Hashtable(); 385 getProperties(tc,d,false,false); 386 Serializable mappedValue = pf.doValidateApplyAndMap(tc, key, 387 value, d, dbOnlyProperty); 388 if (key.equals(Attribute.LOG_DEVICE)) 391 { 392 throw StandardException.newException( 393 SQLState.RAWSTORE_CANNOT_CHANGE_LOGDEVICE); 394 } 395 396 if (mappedValue == null) 397 return value; 398 else 399 return mappedValue; 400 } 401 402 410 private Serializable map(String key, 411 Serializable value, 412 Dictionary set) 413 throws StandardException 414 { 415 return pf.doMap(key, value, set); 416 } 417 418 426 427 private void validate(String key, 428 Serializable value, 429 Dictionary set) 430 throws StandardException 431 { 432 pf.validateSingleProperty(key, value, set); 433 } 434 435 436 private boolean bootPasswordChange(TransactionController tc, 437 String key, 438 Serializable value) 439 throws StandardException 440 { 441 if (key.equals(Attribute.BOOT_PASSWORD)) 445 { 446 AccessFactory af = ((TransactionManager)tc).getAccessManager(); 452 453 RawStoreFactory rsf = (RawStoreFactory) 454 Monitor.findServiceModule(af, RawStoreFactory.MODULE); 455 456 serviceProperties.remove(Attribute.BOOT_PASSWORD); 458 459 value = rsf.changeBootPassword(serviceProperties, value); 460 serviceProperties.put(RawStoreFactory.ENCRYPTED_KEY,value); 461 return true; 462 } 463 else 464 { 465 return false; 466 } 467 } 468 469 489 void setProperty( 490 TransactionController tc, 491 String key, 492 Serializable value, boolean dbOnlyProperty) 493 throws StandardException 494 { 495 if (SanityManager.DEBUG) 496 { 497 498 if (!((value == null) || (value instanceof Formatable))) 499 { 500 if (!(value.getClass().getName().startsWith("java."))) 501 { 502 SanityManager.THROWASSERT( 503 "Non-formattable, non-java class - " + 504 value.getClass().getName()); 505 } 506 } 507 } 508 509 lockProperties(tc); 510 Serializable valueToValidateAndApply = value; 511 if (value == null) 514 valueToValidateAndApply = getPropertyDefault(tc,key); 515 Serializable valueToSave = 516 validateApplyAndMap(tc,key,valueToValidateAndApply, dbOnlyProperty); 517 518 if (bootPasswordChange(tc,key,value)) 522 return; 523 524 else if (value==null) 530 saveProperty(tc,key,null); 531 else 536 saveProperty(tc,key,valueToSave); 537 } 538 539 private Serializable readProperty(TransactionController tc, 540 String key) throws StandardException 541 { 542 ScanController scan = openScan(tc, key, 0); 544 545 DataValueDescriptor[] row = makeNewTemplate(); 546 547 boolean isThere = scan.fetchNext(row); 549 550 scan.close(); 551 552 if (!isThere) return null; 553 554 return (Serializable ) (((UserType) row[1]).getObject()); 555 } 556 557 private Serializable getCachedProperty(TransactionController tc, 558 String key) throws StandardException 559 { 560 Dictionary dbProps = getCachedDbProperties(tc); 563 564 if (dbProps.get(key) != null) 567 return (Serializable ) dbProps.get(key); 568 else 569 return getCachedPropertyDefault(tc,key,dbProps); 570 } 571 572 private Serializable getCachedPropertyDefault(TransactionController tc, 573 String key, 574 Dictionary dbProps) 575 throws StandardException 576 { 577 if (dbProps == null) dbProps = getCachedDbProperties(tc); 580 Dictionary defaults = (Dictionary)dbProps.get(AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); 583 if (defaults == null) 584 return null; 585 else 586 return (Serializable )defaults.get(key); 587 } 588 589 608 Serializable getProperty( 609 TransactionController tc, 610 String key) 611 throws StandardException 612 { 613 if(PropertyUtil.isServiceProperty(key)) return serviceProperties.getProperty(key); 616 617 if (iHoldTheUpdateLock(tc)) 620 { 621 Serializable v = readProperty(tc,key); 624 if (v != null) return v; 625 626 return getPropertyDefault(tc,key); 627 } 628 else 629 { 630 return getCachedProperty(tc,key); 631 } 632 } 633 634 638 Serializable getPropertyDefault(TransactionController tc, String key) 639 throws StandardException 640 { 641 if (iHoldTheUpdateLock(tc)) 644 { 645 Dictionary defaults = (Dictionary)readProperty(tc,AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); 649 if (defaults == null) 650 return null; 651 else 652 return (Serializable )defaults.get(key); 653 } 654 else 655 { 656 return getCachedPropertyDefault(tc,key,null); 657 } 658 } 659 660 private Dictionary copyValues(Dictionary to, Dictionary from, boolean stringsOnly) 661 { 662 if (from == null) return to; 663 for (Enumeration keys = from.keys(); keys.hasMoreElements(); ) { 664 String key = (String ) keys.nextElement(); 665 Object value = from.get(key); 666 if ((value instanceof String ) || !stringsOnly) 667 to.put(key, value); 668 } 669 return to; 670 } 671 672 676 Properties getProperties(TransactionController tc) throws StandardException { 677 Properties p = new Properties (); 678 getProperties(tc,p,true,false); 679 return p; 680 } 681 682 public void getProperties(TransactionController tc, 683 Dictionary d, 684 boolean stringsOnly, 685 boolean defaultsOnly) throws StandardException 686 { 687 if (iHoldTheUpdateLock(tc)) 690 { 691 Dictionary dbProps = readDbProperties(tc); 692 Dictionary defaults = (Dictionary)dbProps.get(AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); 693 copyValues(d,defaults,stringsOnly); 694 if (!defaultsOnly)copyValues(d,dbProps,stringsOnly); 695 } 696 else 697 { 698 Dictionary dbProps = getCachedDbProperties(tc); 699 Dictionary defaults = (Dictionary)dbProps.get(AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); 700 copyValues(d,defaults,stringsOnly); 701 if (!defaultsOnly)copyValues(d,dbProps,stringsOnly); 702 } 703 } 704 705 void resetCache() {cachedSet = null;} 706 707 708 private Dictionary readDbProperties(TransactionController tc) 709 throws StandardException 710 { 711 Dictionary set = new Hashtable(); 712 713 ScanController scan = openScan(tc, (String ) null, 0); 715 716 DataValueDescriptor[] row = makeNewTemplate(); 717 718 while (scan.fetchNext(row)) { 719 720 Object key = ((UserType) row[0]).getObject(); 721 Object value = ((UserType) row[1]).getObject(); 722 if (SanityManager.DEBUG) { 723 if (!(key instanceof String )) 724 SanityManager.THROWASSERT( 725 "Key is not a string " + key.getClass().getName()); 726 } 727 set.put(key, value); 728 } 729 scan.close(); 730 731 for (int i = 0; i < PropertyUtil.servicePropertyList.length; i++) { 733 String value = 734 serviceProperties.getProperty(PropertyUtil.servicePropertyList[i]); 735 if (value != null) set.put(PropertyUtil.servicePropertyList[i], value); 736 } 737 return set; 738 } 739 740 private Dictionary getCachedDbProperties(TransactionController tc) 741 throws StandardException 742 { 743 Dictionary dbProps = cachedSet; 744 if (dbProps == null) 746 { 747 dbProps = readDbProperties(tc); 748 cachedSet = dbProps; 749 } 750 751 return dbProps; 752 } 753 754 755 void lockProperties(TransactionController tc) throws StandardException 756 { 757 Object csGroup = tc.getLockObject(); 764 lf.lockObject(csGroup, csGroup, cachedLock, ShExQual.EX, C_LockFactory.TIMED_WAIT); 765 } 766 767 771 private boolean iHoldTheUpdateLock(TransactionController tc) throws StandardException 772 { 773 Object csGroup = tc.getLockObject(); 774 return lf.isLockHeld(csGroup, csGroup, cachedLock, ShExQual.EX); 775 } 776 } 777 778 781 class CacheLock extends ShExLockable { 782 783 private PropertyConglomerate pc; 784 785 CacheLock(PropertyConglomerate pc) { 786 this.pc = pc; 787 } 788 789 public void unlockEvent(Latch lockInfo) 790 { 791 super.unlockEvent(lockInfo); 792 pc.resetCache(); 793 } 794 } 795 | Popular Tags |