@Override
 public int commit() {
   int updated = findDifference();
   for (String key : changes.keySet()) {
     cache.put(key, changes.get(key));
   }
   changes.clear();
   for (String key : cache.keySet()) {
     changes.put(key, cache.get(key));
   }
   boolean isClosed = true;
   DataInputStream[][] inputStreams = new DataInputStream[partsNumber][partsNumber];
   DataOutputStream[][] outputStreams = new DataOutputStream[partsNumber][partsNumber];
   try {
     for (int i = 0; i < partsNumber; i++) {
       if (!directoriesList[i].exists()) {
         if (!directoriesList[i].mkdir()) {
           throw new IOException(directoriesList[i].getPath() + ": couldn't create directory");
         }
       }
       for (int j = 0; j < partsNumber; j++) {
         if (!filesList[i][j].exists()) {
           if (!filesList[i][j].createNewFile()) {
             throw new IOException(filesList[i][j].getAbsolutePath() + ": couldn't create file");
           }
         }
         if (!filesList[i][j].renameTo(new File(filesList[i][j].getPath() + "~"))) {
           throw new IOException(filesList[i][j].getAbsolutePath() + ": couldn't rename file");
         }
         inputStreams[i][j] =
             new DataInputStream(new FileInputStream(filesList[i][j].getPath() + "~"));
         outputStreams[i][j] = new DataOutputStream(new FileOutputStream(filesList[i][j]));
         DataInputStream inputStream = inputStreams[i][j];
         DataOutputStream outputStream = outputStreams[i][j];
         String nextKey;
         String nextValue;
         String[] pair;
         while ((pair = readNextPair(inputStream)) != null) {
           nextKey = pair[0];
           nextValue = pair[1];
           if (changes.containsKey(nextKey)) {
             nextValue = changes.get(nextKey);
             changes.remove(nextKey);
           }
           if (nextValue != null) {
             writeNextPair(outputStream, nextKey, nextValue);
           }
         }
       }
     }
     Set<Map.Entry<String, String>> entries = changes.entrySet();
     for (Map.Entry<String, String> entry : entries) {
       if (entry.getValue() != null) {
         byte firstByte = getFirstByte(entry.getKey());
         DataOutputStream outputStream =
             outputStreams[firstByte % partsNumber][(firstByte / partsNumber) % partsNumber];
         try {
           writeNextPair(outputStream, entry.getKey(), entry.getValue());
         } catch (IOException e) {
           throw new IllegalStateException(e.getMessage());
         }
       }
     }
     for (int i = 0; i < partsNumber; i++) {
       for (int j = 0; j < partsNumber; j++) {
         inputStreams[i][j].close();
         outputStreams[i][j].close();
         if (!(new File(filesList[i][j].getPath() + "~")).delete()) {
           throw new IllegalStateException(filesList[i][j].getPath() + "~: couldn't delete file");
         }
         if (filesList[i][j].length() == 0) {
           if (!filesList[i][j].delete()) {
             throw new IllegalStateException(filesList[i][j].getPath() + ": couldn't delete file");
           }
         }
       }
     }
     changes.clear();
     oldRecordNumber = recordNumber;
     for (File directory : directoriesList) {
       if (directory.list().length == 0) {
         if (!directory.delete()) {
           throw new IllegalStateException(
               directory.getAbsolutePath() + ": couldn't delete directory");
         }
       }
     }
   } catch (IOException e) {
     throw new IllegalStateException(e.getMessage());
   } finally {
     for (int i = 0; i < partsNumber; i++) {
       for (int j = 0; j < partsNumber; j++) {
         try {
           if (inputStreams[i][j] != null) {
             inputStreams[i][j].close();
           }
         } catch (Exception e) {
           isClosed = false;
         }
         try {
           if (outputStreams[i][j] != null) {
             outputStreams[i][j].close();
           }
         } catch (Exception e) {
           isClosed = false;
         }
       }
     }
   }
   if (!isClosed) {
     throw new IllegalStateException("couldn't close some files");
   }
   return updated;
 }