mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 20:59:54 +01:00
Use immutable collections for thread safety.
This commit is contained in:
@@ -13,6 +13,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
@@ -461,7 +462,7 @@ DatabaseCleaner.Callback {
|
|||||||
|
|
||||||
public boolean generateBatch(ContactId c, BatchWriter b) throws DbException,
|
public boolean generateBatch(ContactId c, BatchWriter b) throws DbException,
|
||||||
IOException {
|
IOException {
|
||||||
Collection<MessageId> ids = new ArrayList<MessageId>();
|
Collection<MessageId> ids;
|
||||||
Collection<Bytes> messages = new ArrayList<Bytes>();
|
Collection<Bytes> messages = new ArrayList<Bytes>();
|
||||||
// Get some sendable messages from the database
|
// Get some sendable messages from the database
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
@@ -593,7 +594,8 @@ DatabaseCleaner.Callback {
|
|||||||
|
|
||||||
public Collection<MessageId> generateOffer(ContactId c, OfferWriter o)
|
public Collection<MessageId> generateOffer(ContactId c, OfferWriter o)
|
||||||
throws DbException, IOException {
|
throws DbException, IOException {
|
||||||
Collection<MessageId> sendable, sent = new ArrayList<MessageId>();
|
Collection<MessageId> sendable;
|
||||||
|
List<MessageId> sent = new ArrayList<MessageId>();
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
@@ -623,7 +625,7 @@ DatabaseCleaner.Callback {
|
|||||||
sent.add(m);
|
sent.add(m);
|
||||||
}
|
}
|
||||||
if(!sent.isEmpty()) o.finish();
|
if(!sent.isEmpty()) o.finish();
|
||||||
return sent;
|
return Collections.unmodifiableList(sent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateSubscriptionUpdate(ContactId c,
|
public void generateSubscriptionUpdate(ContactId c,
|
||||||
@@ -1427,7 +1429,7 @@ DatabaseCleaner.Callback {
|
|||||||
|
|
||||||
public void setVisibility(GroupId g, Collection<ContactId> visible)
|
public void setVisibility(GroupId g, Collection<ContactId> visible)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
Collection<ContactId> affected;
|
List<ContactId> affected;
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
subscriptionLock.writeLock().lock();
|
subscriptionLock.writeLock().lock();
|
||||||
@@ -1464,8 +1466,10 @@ DatabaseCleaner.Callback {
|
|||||||
contactLock.readLock().unlock();
|
contactLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
// Call the listeners outside the lock
|
// Call the listeners outside the lock
|
||||||
if(!affected.isEmpty())
|
if(!affected.isEmpty()) {
|
||||||
|
affected = Collections.unmodifiableList(affected);
|
||||||
callListeners(new SubscriptionsUpdatedEvent(affected));
|
callListeners(new SubscriptionsUpdatedEvent(affected));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void subscribe(Group g) throws DbException {
|
public void subscribe(Group g) throws DbException {
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ public class FontManagerImpl implements FontManager {
|
|||||||
// Use Padauk for Burmese
|
// Use Padauk for Burmese
|
||||||
new BundledFont("Padauk.ttf", 14f, new String[] { "my" }),
|
new BundledFont("Padauk.ttf", 14f, new String[] { "my" }),
|
||||||
// Use DroidSansFallback for Chinese, Japanese and Korean
|
// Use DroidSansFallback for Chinese, Japanese and Korean
|
||||||
new BundledFont("DroidSansFallback.ttf", 12f, new String[] { "zh" , "ja", "ko" }),
|
new BundledFont("DroidSansFallback.ttf", 12f,
|
||||||
|
new String[] { "zh" , "ja", "ko" })
|
||||||
};
|
};
|
||||||
|
|
||||||
// Map from languages to fonts
|
// Map from languages to fonts
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.lifecycle;
|
package net.sf.briar.lifecycle;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@@ -38,10 +39,11 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl {
|
|||||||
|
|
||||||
WindowsShutdownManagerImpl() {
|
WindowsShutdownManagerImpl() {
|
||||||
// Use the Unicode versions of Win32 API calls
|
// Use the Unicode versions of Win32 API calls
|
||||||
options = new HashMap<String, Object>();
|
Map<String, Object> m = new HashMap<String, Object>();
|
||||||
options.put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
|
m.put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
|
||||||
options.put(Library.OPTION_FUNCTION_MAPPER,
|
m.put(Library.OPTION_FUNCTION_MAPPER,
|
||||||
W32APIFunctionMapper.UNICODE);
|
W32APIFunctionMapper.UNICODE);
|
||||||
|
options = Collections.unmodifiableMap(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ class PluginManagerImpl implements PluginManager {
|
|||||||
private final Poller poller;
|
private final Poller poller;
|
||||||
private final ConnectionDispatcher dispatcher;
|
private final ConnectionDispatcher dispatcher;
|
||||||
private final UiCallback uiCallback;
|
private final UiCallback uiCallback;
|
||||||
private final List<BatchPlugin> batchPlugins;
|
private final List<BatchPlugin> batchPlugins; // Locking: this
|
||||||
private final List<StreamPlugin> streamPlugins;
|
private final List<StreamPlugin> streamPlugins; // Locking: this
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PluginManagerImpl(DatabaseComponent db, Executor executor, Poller poller,
|
PluginManagerImpl(DatabaseComponent db, Executor executor, Poller poller,
|
||||||
@@ -156,7 +156,7 @@ class PluginManagerImpl implements PluginManager {
|
|||||||
List<Plugin> plugins = new ArrayList<Plugin>();
|
List<Plugin> plugins = new ArrayList<Plugin>();
|
||||||
plugins.addAll(batchPlugins);
|
plugins.addAll(batchPlugins);
|
||||||
plugins.addAll(streamPlugins);
|
plugins.addAll(streamPlugins);
|
||||||
poller.startPolling(plugins);
|
poller.startPolling(Collections.unmodifiableList(plugins));
|
||||||
// Return the number of plugins successfully started
|
// Return the number of plugins successfully started
|
||||||
return batchPlugins.size() + streamPlugins.size();
|
return batchPlugins.size() + streamPlugins.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,7 +241,8 @@ class BluetoothPlugin extends AbstractPlugin implements StreamPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ContactListener listener = new ContactListener(discoveryAgent,
|
ContactListener listener = new ContactListener(discoveryAgent,
|
||||||
addresses, uuids);
|
Collections.unmodifiableMap(addresses),
|
||||||
|
Collections.unmodifiableMap(uuids));
|
||||||
synchronized(discoveryLock) {
|
synchronized(discoveryLock) {
|
||||||
try {
|
try {
|
||||||
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, listener);
|
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, listener);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package net.sf.briar.plugins.file;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
|
|||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
List<File> drives = finder.findRemovableDrives();
|
Collection<File> drives = finder.findRemovableDrives();
|
||||||
while(running) {
|
while(running) {
|
||||||
synchronized(pollingLock) {
|
synchronized(pollingLock) {
|
||||||
try {
|
try {
|
||||||
@@ -58,7 +58,7 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!running) return;
|
if(!running) return;
|
||||||
List<File> newDrives = finder.findRemovableDrives();
|
Collection<File> newDrives = finder.findRemovableDrives();
|
||||||
for(File f : newDrives) {
|
for(File f : newDrives) {
|
||||||
if(!drives.contains(f)) callback.driveInserted(f);
|
if(!drives.contains(f)) callback.driveInserted(f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package net.sf.briar.plugins.file;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.Collection;
|
||||||
|
|
||||||
interface RemovableDriveFinder {
|
interface RemovableDriveFinder {
|
||||||
|
|
||||||
List<File> findRemovableDrives() throws IOException;
|
Collection<File> findRemovableDrives() throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@@ -69,7 +70,8 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
@Override
|
@Override
|
||||||
protected File chooseOutputDirectory() {
|
protected File chooseOutputDirectory() {
|
||||||
try {
|
try {
|
||||||
List<File> drives = finder.findRemovableDrives();
|
List<File> drives =
|
||||||
|
new ArrayList<File>(finder.findRemovableDrives());
|
||||||
if(drives.isEmpty()) return null;
|
if(drives.isEmpty()) return null;
|
||||||
String[] paths = new String[drives.size()];
|
String[] paths = new String[drives.size()];
|
||||||
for(int i = 0; i < paths.length; i++) {
|
for(int i = 0; i < paths.length; i++) {
|
||||||
@@ -96,7 +98,7 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Collection<File> findFilesByName(String filename) {
|
protected Collection<File> findFilesByName(String filename) {
|
||||||
Collection<File> matches = new ArrayList<File>();
|
List<File> matches = new ArrayList<File>();
|
||||||
try {
|
try {
|
||||||
for(File drive : finder.findRemovableDrives()) {
|
for(File drive : finder.findRemovableDrives()) {
|
||||||
File[] files = drive.listFiles();
|
File[] files = drive.listFiles();
|
||||||
@@ -110,7 +112,7 @@ implements RemovableDriveMonitor.Callback {
|
|||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
|
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.getMessage());
|
||||||
}
|
}
|
||||||
return matches;
|
return Collections.unmodifiableList(matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void driveInserted(File root) {
|
public void driveInserted(File root) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.sf.briar.plugins.file;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
@@ -34,6 +35,6 @@ abstract class UnixRemovableDriveFinder implements RemovableDriveFinder {
|
|||||||
} finally {
|
} finally {
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
return drives;
|
return Collections.unmodifiableList(drives);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ import net.contentobjects.jnotify.JNotifyListener;
|
|||||||
abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor,
|
abstract class UnixRemovableDriveMonitor implements RemovableDriveMonitor,
|
||||||
JNotifyListener {
|
JNotifyListener {
|
||||||
|
|
||||||
|
// Locking: this
|
||||||
private final List<Integer> watches = new ArrayList<Integer>();
|
private final List<Integer> watches = new ArrayList<Integer>();
|
||||||
|
|
||||||
private boolean started = false;
|
private boolean started = false; // Locking: this
|
||||||
private Callback callback = null;
|
private Callback callback = null; // Locking: this
|
||||||
|
|
||||||
protected abstract String[] getPathsToWatch();
|
protected abstract String[] getPathsToWatch();
|
||||||
|
|
||||||
@@ -37,11 +38,9 @@ JNotifyListener {
|
|||||||
watches.clear();
|
watches.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fileCreated(int wd, String rootPath, String name) {
|
public synchronized void fileCreated(int wd, String rootPath, String name) {
|
||||||
synchronized(this) {
|
if(!started) throw new IllegalStateException();
|
||||||
if(!started) throw new IllegalStateException();
|
callback.driveInserted(new File(rootPath + "/" + name));
|
||||||
callback.driveInserted(new File(rootPath + "/" + name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fileDeleted(int wd, String rootPath, String name) {
|
public void fileDeleted(int wd, String rootPath, String name) {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package net.sf.briar.plugins.file;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.Kernel32;
|
import com.sun.jna.platform.win32.Kernel32;
|
||||||
@@ -12,7 +14,7 @@ class WindowsRemovableDriveFinder implements RemovableDriveFinder {
|
|||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364939.aspx
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364939.aspx
|
||||||
private static final int DRIVE_REMOVABLE = 2;
|
private static final int DRIVE_REMOVABLE = 2;
|
||||||
|
|
||||||
public List<File> findRemovableDrives() throws IOException {
|
public Collection<File> findRemovableDrives() throws IOException {
|
||||||
File[] roots = File.listRoots();
|
File[] roots = File.listRoots();
|
||||||
if(roots == null) throw new IOException();
|
if(roots == null) throw new IOException();
|
||||||
List<File> drives = new ArrayList<File>();
|
List<File> drives = new ArrayList<File>();
|
||||||
@@ -24,7 +26,6 @@ class WindowsRemovableDriveFinder implements RemovableDriveFinder {
|
|||||||
throw new IOException(e.getMessage());
|
throw new IOException(e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drives;
|
return Collections.unmodifiableList(drives);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package net.sf.briar.serial;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -14,12 +15,13 @@ import net.sf.briar.api.serial.Consumer;
|
|||||||
import net.sf.briar.api.serial.ObjectReader;
|
import net.sf.briar.api.serial.ObjectReader;
|
||||||
import net.sf.briar.api.serial.Reader;
|
import net.sf.briar.api.serial.Reader;
|
||||||
|
|
||||||
|
// This class is not thread-safe
|
||||||
class ReaderImpl implements Reader {
|
class ReaderImpl implements Reader {
|
||||||
|
|
||||||
private static final byte[] EMPTY_BUFFER = new byte[] {};
|
private static final byte[] EMPTY_BUFFER = new byte[] {};
|
||||||
|
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final List<Consumer> consumers = new ArrayList<Consumer>(0);
|
private final Collection<Consumer> consumers = new ArrayList<Consumer>(0);
|
||||||
|
|
||||||
private ObjectReader<?>[] objectReaders = new ObjectReader<?>[] {};
|
private ObjectReader<?>[] objectReaders = new ObjectReader<?>[] {};
|
||||||
private boolean hasLookahead = false, eof = false;
|
private boolean hasLookahead = false, eof = false;
|
||||||
@@ -346,7 +348,7 @@ class ReaderImpl implements Reader {
|
|||||||
List<E> list = new ArrayList<E>();
|
List<E> list = new ArrayList<E>();
|
||||||
while(!hasEnd()) list.add(readObject(e));
|
while(!hasEnd()) list.add(readObject(e));
|
||||||
readEnd();
|
readEnd();
|
||||||
return list;
|
return Collections.unmodifiableList(list);
|
||||||
} else {
|
} else {
|
||||||
int length = 0xFF & next ^ Tag.SHORT_LIST;
|
int length = 0xFF & next ^ Tag.SHORT_LIST;
|
||||||
return readList(e, length);
|
return readList(e, length);
|
||||||
@@ -358,7 +360,7 @@ class ReaderImpl implements Reader {
|
|||||||
if(length == 0) return Collections.emptyList();
|
if(length == 0) return Collections.emptyList();
|
||||||
List<E> list = new ArrayList<E>();
|
List<E> list = new ArrayList<E>();
|
||||||
for(int i = 0; i < length; i++) list.add(readObject(e));
|
for(int i = 0; i < length; i++) list.add(readObject(e));
|
||||||
return list;
|
return Collections.unmodifiableList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasEnd() throws IOException {
|
private boolean hasEnd() throws IOException {
|
||||||
@@ -478,7 +480,7 @@ class ReaderImpl implements Reader {
|
|||||||
throw new FormatException(); // Duplicate key
|
throw new FormatException(); // Duplicate key
|
||||||
}
|
}
|
||||||
readEnd();
|
readEnd();
|
||||||
return m;
|
return Collections.unmodifiableMap(m);
|
||||||
} else {
|
} else {
|
||||||
int size = 0xFF & next ^ Tag.SHORT_MAP;
|
int size = 0xFF & next ^ Tag.SHORT_MAP;
|
||||||
return readMap(k, v, size);
|
return readMap(k, v, size);
|
||||||
@@ -494,7 +496,7 @@ class ReaderImpl implements Reader {
|
|||||||
if(m.put(readObject(k), readObject(v)) != null)
|
if(m.put(readObject(k), readObject(v)) != null)
|
||||||
throw new FormatException(); // Duplicate key
|
throw new FormatException(); // Duplicate key
|
||||||
}
|
}
|
||||||
return m;
|
return Collections.unmodifiableMap(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasMapStart() throws IOException {
|
public boolean hasMapStart() throws IOException {
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ import net.sf.briar.api.Bytes;
|
|||||||
import net.sf.briar.api.serial.Consumer;
|
import net.sf.briar.api.serial.Consumer;
|
||||||
import net.sf.briar.api.serial.Writer;
|
import net.sf.briar.api.serial.Writer;
|
||||||
|
|
||||||
|
// This class is not thread-safe
|
||||||
class WriterImpl implements Writer {
|
class WriterImpl implements Writer {
|
||||||
|
|
||||||
private final OutputStream out;
|
private final OutputStream out;
|
||||||
private final List<Consumer> consumers = new ArrayList<Consumer>(0);
|
private final Collection<Consumer> consumers = new ArrayList<Consumer>(0);
|
||||||
|
|
||||||
WriterImpl(OutputStream out) {
|
WriterImpl(OutputStream out) {
|
||||||
this.out = out;
|
this.out = out;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.sf.briar.api.protocol.TransportIndex;
|
|||||||
import net.sf.briar.api.transport.ConnectionWindow;
|
import net.sf.briar.api.transport.ConnectionWindow;
|
||||||
import net.sf.briar.util.ByteUtils;
|
import net.sf.briar.util.ByteUtils;
|
||||||
|
|
||||||
|
// This class is not thread-safe
|
||||||
class ConnectionWindowImpl implements ConnectionWindow {
|
class ConnectionWindowImpl implements ConnectionWindow {
|
||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import java.io.OutputStream;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -58,11 +60,10 @@ abstract class StreamConnection implements DatabaseListener {
|
|||||||
protected final ContactId contactId;
|
protected final ContactId contactId;
|
||||||
protected final StreamTransportConnection connection;
|
protected final StreamTransportConnection connection;
|
||||||
|
|
||||||
// These fields must only be accessed with this's lock held
|
private int writerFlags = 0; // Locking: this
|
||||||
private int writerFlags = 0;
|
private Collection<MessageId> offered = null; // Locking: this
|
||||||
private Collection<MessageId> offered = null;
|
private LinkedList<MessageId> requested = null; // Locking: this
|
||||||
private Collection<MessageId> requested = null;
|
private Offer incomingOffer = null; // Locking: this
|
||||||
private Offer incomingOffer = null;
|
|
||||||
|
|
||||||
StreamConnection(ConnectionReaderFactory connReaderFactory,
|
StreamConnection(ConnectionReaderFactory connReaderFactory,
|
||||||
ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
|
ConnectionWriterFactory connWriterFactory, DatabaseComponent db,
|
||||||
@@ -143,15 +144,15 @@ abstract class StreamConnection implements DatabaseListener {
|
|||||||
}
|
}
|
||||||
// Work out which messages were requested
|
// Work out which messages were requested
|
||||||
BitSet b = r.getBitmap();
|
BitSet b = r.getBitmap();
|
||||||
Collection<MessageId> req = new LinkedList<MessageId>();
|
LinkedList<MessageId> req = new LinkedList<MessageId>();
|
||||||
Collection<MessageId> seen = new ArrayList<MessageId>();
|
List<MessageId> seen = new ArrayList<MessageId>();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(MessageId m : off) {
|
for(MessageId m : off) {
|
||||||
if(b.get(i++)) req.add(m);
|
if(b.get(i++)) req.add(m);
|
||||||
else seen.add(m);
|
else seen.add(m);
|
||||||
}
|
}
|
||||||
// Mark the unrequested messages as seen
|
// Mark the unrequested messages as seen
|
||||||
db.setSeen(contactId, seen);
|
db.setSeen(contactId, Collections.unmodifiableList(seen));
|
||||||
// Store the requested message IDs and notify the writer
|
// Store the requested message IDs and notify the writer
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if(requested != null)
|
if(requested != null)
|
||||||
|
|||||||
Reference in New Issue
Block a user