Browse Source

ignore usagemap inconsistencies in certain situations

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@499 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-1.2.2
James Ahlborn 13 years ago
parent
commit
7bd23681d1

+ 3
- 0
src/changes/changes.xml View File

Add support for custom column value matching when finding rows using a Add support for custom column value matching when finding rows using a
Cursor. Cursor.
</action> </action>
<action dev="jahlborn" type="fix">
Ignore usagemap inconsistencies in certain situations.
</action>
</release> </release>
<release version="1.2.1" date="2010-08-01"> <release version="1.2.1" date="2010-08-01">
<action dev="jahlborn" type="add" issue="3005272"> <action dev="jahlborn" type="add" issue="3005272">

+ 3
- 1
src/java/com/healthmarketscience/jackcess/PageChannel.java View File

int pageNumber = getNextPageNumber(size); int pageNumber = getNextPageNumber(size);
_channel.write(_codecHandler.encodePage(page, pageNumber, pageOffset), _channel.write(_codecHandler.encodePage(page, pageNumber, pageOffset),
offset); offset);
_globalUsageMap.removePageNumber(pageNumber); //force is done here
// note, we "force" page removal because we know that this is an unused
// page (since we just added it to the file)
_globalUsageMap.removePageNumber(pageNumber, true);
return pageNumber; return pageNumber;
} }



+ 52
- 11
src/java/com/healthmarketscience/jackcess/UsageMap.java View File

*/ */
public void addPageNumber(int pageNumber) throws IOException { public void addPageNumber(int pageNumber) throws IOException {
++_modCount; ++_modCount;
_handler.addOrRemovePageNumber(pageNumber, true);
_handler.addOrRemovePageNumber(pageNumber, true, false);
} }
/** /**
* Remove a page number from this usage map * Remove a page number from this usage map
*/ */
public void removePageNumber(int pageNumber) throws IOException { public void removePageNumber(int pageNumber) throws IOException {
removePageNumber(pageNumber, false);
}

/**
* Remove a page number from this usage map
*/
protected void removePageNumber(int pageNumber, boolean force)
throws IOException
{
++_modCount; ++_modCount;
_handler.addOrRemovePageNumber(pageNumber, false);
_handler.addOrRemovePageNumber(pageNumber, false, force);
} }
protected void updateMap(int absolutePageNumber, protected void updateMap(int absolutePageNumber,
int bufferRelativePageNumber, int bufferRelativePageNumber,
ByteBuffer buffer, boolean add)
ByteBuffer buffer, boolean add, boolean force)
throws IOException throws IOException
{ {
//Find the byte to which to apply the bitmask and create the bitmask //Find the byte to which to apply the bitmask and create the bitmask
// check current value for this page number // check current value for this page number
int pageNumberOffset = pageNumberToBitIndex(absolutePageNumber); int pageNumberOffset = pageNumberToBitIndex(absolutePageNumber);
boolean isOn = _pageNumbers.get(pageNumberOffset); boolean isOn = _pageNumbers.get(pageNumberOffset);
if(isOn == add) {
if((isOn == add) && !force) {
throw new IOException("Page number " + absolutePageNumber + " already " + throw new IOException("Page number " + absolutePageNumber + " already " +
((add) ? "added to" : "removed from") + ((add) ? "added to" : "removed from") +
" usage map, expected range " + " usage map, expected range " +
StringBuilder builder = new StringBuilder( StringBuilder builder = new StringBuilder(
"(" + _handler.getClass().getSimpleName() + "(" + _handler.getClass().getSimpleName() +
") page numbers (range " + _startPage + " " + _endPage + "): ["); ") page numbers (range " + _startPage + " " + _endPage + "): [");

PageCursor pCursor = cursor(); PageCursor pCursor = cursor();
int curRangeStart = Integer.MIN_VALUE;
int prevPage = Integer.MIN_VALUE;
while(true) { while(true) {
int nextPage = pCursor.getNextPage(); int nextPage = pCursor.getNextPage();
if(nextPage < 0) { if(nextPage < 0) {
break; break;
} }
builder.append(nextPage).append(", ");

if(nextPage != (prevPage + 1)) {
if(prevPage >= 0) {
rangeToString(builder, curRangeStart, prevPage);
}
curRangeStart = nextPage;
}
prevPage = nextPage;
}
if(prevPage >= 0) {
rangeToString(builder, curRangeStart, prevPage);
} }

builder.append("]"); builder.append("]");
return builder.toString(); return builder.toString();
} }

private static void rangeToString(StringBuilder builder, int rangeStart,
int rangeEnd)
{
builder.append(rangeStart);
if(rangeEnd > rangeStart) {
builder.append("-").append(rangeEnd);
}
builder.append(", ");
}
private abstract class Handler private abstract class Handler
{ {
/** /**
* @param pageNumber Page number to add or remove from this map * @param pageNumber Page number to add or remove from this map
* @param add True to add it, false to remove it * @param add True to add it, false to remove it
* @param force true to force add/remove and ignore certain inconsistencies
*/ */
public abstract void addOrRemovePageNumber(int pageNumber, boolean add)
public abstract void addOrRemovePageNumber(int pageNumber, boolean add,
boolean force)
throws IOException; throws IOException;
} }


} }
@Override @Override
public void addOrRemovePageNumber(int pageNumber, boolean add)
public void addOrRemovePageNumber(int pageNumber, boolean add,
boolean force)
throws IOException throws IOException
{ {
if(isPageWithinRange(pageNumber)) { if(isPageWithinRange(pageNumber)) {


// easy enough, just update the inline data // easy enough, just update the inline data
int bufferRelativePageNumber = pageNumberToBitIndex(pageNumber); int bufferRelativePageNumber = pageNumberToBitIndex(pageNumber);
updateMap(pageNumber, bufferRelativePageNumber, getTableBuffer(), add);
updateMap(pageNumber, bufferRelativePageNumber, getTableBuffer(), add,
force);
// Write the updated map back to disk // Write the updated map back to disk
writeTable(); writeTable();
} }
} else {
} else if(!force) {


// this should not happen, we are removing a page which is not in // this should not happen, we are removing a page which is not in
// the map // the map
} }
@Override @Override
public void addOrRemovePageNumber(int pageNumber, boolean add)
public void addOrRemovePageNumber(int pageNumber, boolean add,
boolean force)
throws IOException throws IOException
{ {
if(!isPageWithinRange(pageNumber)) { if(!isPageWithinRange(pageNumber)) {
if(force) {
return;
}
throw new IOException("Page number " + pageNumber + throw new IOException("Page number " + pageNumber +
" is out of supported range"); " is out of supported range");
} }
} }
updateMap(pageNumber, updateMap(pageNumber,
(pageNumber - (getMaxPagesPerUsagePage() * pageIndex)), (pageNumber - (getMaxPagesPerUsagePage() * pageIndex)),
mapPageBuffer, add);
mapPageBuffer, add, force);
getPageChannel().writePage(mapPageBuffer, mapPageNum); getPageChannel().writePage(mapPageBuffer, mapPageNum);
} }

Loading…
Cancel
Save